2.2 Выбор методов решения задачи и разработка основных алгоритмов предметной области

Для вычитания двух стековых регистров, приводим порядок к одному значению и вычитаем мантиссы. Далее если необходимо производим нормализацию. Если в результате произошло переполнение мантиссы или порядка, устанавливаем флаги и возвращаем 0.

 

2.3 Построение структурной схемы программного продукта

Для работы программы необходимы следующие функции:

int main() – главная функция программы в ней вызываеться функция инициализации, заполнение стека сопроцессора, а также в диалоговом режиме вызываеться FSUB.

int fld(str reg[],_sreg &sreg,_creg creg,_twr twr,int st0 ,int stimm)– заполнение стека сопроцессора.

int print_st(str reg[],_sreg sreg,_creg creg,_twr twr, int id)– печатает 1-й элемент стека сопроцессора.

int fsub(str reg[],_sreg &sreg,_creg creg,_twr twr,int fl, int s1,int s2)– функция выполняющаяя сложение двух стековых регистров и выталкивает вершину стека.

Структурная схема программного продукта:

Рис.1. Структурная схема программного продукта


3.  Описание реализации программного продукта

3.1 Описание программы эмуляции команды FSUB математического сопроцессора

В функции void main(), с которой начинается выполнение программы, производится инициализация эмулятора сопроцессора, заполнение стека первоначальными значениями, после этого предлагается в диалоговом режиме ввести значение:

1 - fsub

2 - fsub n

3 - fsub st(n), st(n)

4 - fld

0 - выход

В случае если пользователь введет 1, программа вычтет из вершины стека значение, находящееся на следующей позиции, 2 – вычтет из вершины стека переменную, введенную пользователем, 3 – произведет вычитание указанных пользователем значений стека, 4 – поместит на вершину стека новое значение.

3.2 Описание функции FSUB

Логика работы функции представлена блок-схемой на рис.3.1.


Рис.3.1. Лист 1


Рис.3.1. Лист 2

3.3 Описание функции FLD

Логика работы функции представлена блок-схемой на рис.3.2.


Рис.3.2. Лист 1


Рис.3.2. Лист 2

3.4 Описание функции Print_st

Логика работы функции представлена блок-схемой на рис.3.3.


Рис.3.3. Лист 1


4.  Тестирование программы

4.1 Выбор стратегии тестирования и разработка тестов

Для проверки работоспособности программы необходимо разработать такой тест, чтобы он проверил все возможные случаи, которые могут возникнуть при пользовании этой программой. Для этого составим набор тестов:

План тестирования:

1.  Вычтем регистры st0 и st1 командой fsub

2.  Вычтем регистр st0 и переменную n командой fsub n

3.  Вычтем регистры st1 и st5 командой fsub st1, st5

4.  Вычтем регистры st0 и st2 командой fsub st0, st2

5.  Вычтем регистры st0 и st3 командой fsub st0, st3

6.  Вычтем регистры st0 и st6 командой fsub st0, st6

7.  Вычтем регистры st0 и st7 командой fsub st0, st7

8.  Вычтем регистры st0 и st7 командой fsub st0, st4

Результаты тестов: Перед тестированием.

twr =98B; swr =E; cwr =D

Таблица 4.1

Название регистра Мантисса Порядок
St0 5,54 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 0
St5 1,12 1
St6 нечисло 0
St7 пусто 0

После 1 теста ( fsub) регистры не изменяются.

Таблица 4.2

Название регистра Мантисса Порядок
St0 -4,008 3
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

После 2 теста ( fsub n, n = -5000,52), регистры не изменяются.

Таблица 4.3

Название регистра Мантисса Порядок
St0 9,9252 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

После 3 теста ( fsub st1, st5), регистры не изменяются.

Таблица 4.4

Название регистра Мантисса Порядок
St0 8,7952 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

 

После 4 теста ( fsub st0, st2).

twr =98B

swr =400E (флаг IE = 1, DE = 1)

cwr =D

Таблица 4.5

Название регистра Мантисса Порядок
St0 8,7952 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

После 5 теста ( fsub st0, st3), регистры неизменны.

Таблица 4.6

Название регистра Мантисса Порядок
St0 8,7952 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

После 6 теста ( fsub st0, st6); twr =98B; swr =600E (флаг IE = 1)

cwr =D


Таблица 4.7

Название регистра Мантисса Порядок
St0 8,7952 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

После 7 теста ( fsub st0, st7).

twr =98B

swr =410E (флаг IE = 1, SF = 1)

cwr =D

Таблица 4.8

Название регистра Мантисса Порядок
St0 8,7952 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

После 8 теста ( fsub st0, st4).

twr =98B

swr =600E (флаг IE = 1)

cwr =D


Таблица 4.9

Название регистра Мантисса Порядок
St0 8,7952 2
St1 4,562 3
St2 денормализованый операнд 0
St3 0 0
St4 бесконечность 5
St5 1,12 1
St6 нечисло 0
St7 пусто 0

Заключение

В результате проделанной работы была написана программа, по своей сути, дублирующая команду математического сопроцессора fsub, а также её вариации. Были изучены и применены на практике в виде эмуляции 3 регистра. Регистор тегов, регистр команд и регистр состояний.

Была изучена система команд процессора 80х87 и принципы работы процессоров. Было получено представление и содержании такого устройства как процессор, что до не давнего времени было известно на уровне "черного ящика".


Приложение

П.1. Текст программы

#include<iostream>

#include<string>

#include<windows.h>

struct bits

{

unsigned char b0 : 1;

unsigned char b1 : 1;

unsigned char b2 : 1;

unsigned char b3 : 1;

unsigned char b4 : 1;

unsigned char b5 : 1;

unsigned char b6 : 1;

unsigned char b7 : 1;

};

union bait_tab

{

bits bit;

unsigned char bait;

};

struct regs

{

unsigned IE: 1; // Ошибка недействительной операции;

unsigned DE: 1; // Ошибка денормализованного операнда;

unsigned ZE: 1; // Ошибка деления на ноль;

unsigned OE: 1; // Ошибка антипереполнения;

unsigned UE: 1; // Ошибка переполнения;

unsigned PE: 1; // Ошибка точности;

unsigned SF: 1; // Бит ошибки работы со стеком;

unsigned ES: 1; // Бит суммарной ошибки;

unsigned C0: 1; // Бит признака (Condition Code);

unsigned C1: 1; // Бит признака (Condition Code);

unsigned C2: 1; // Бит признака (Condition Code);

unsigned TOP:3; // Указатель регистра текущей вершины стека;

unsigned C3: 1; // Бит признака (Condition Code);

unsigned B: 1; // Бит занятости.

};

union _sreg

{

regs data;

unsigned short int sreg;

};

union _creg

{

struct

{

//маски

unsigned IM: 1; // Маска недействительной операции;

unsigned DM: 1; // Маска денормализованного операнда;

unsigned ZM: 1; // Маска деления на ноль;

unsigned OM: 1; // Маска антипереполнения;

unsigned UM: 1; // Маска переполнения;

unsigned PM: 1; // Маска точности;

unsigned PC: 2; // Поле управления точностью;

unsigned RC: 2; // Поле управления округлением.

} data;

unsigned short int creg;

};

union _twr

{

struct

{

unsigned char pr0:2;// 00 - занят допустимым не нулевым значением

//unsigned char pr1:2;// 01 - содержит нулевое значение

//unsigned char pr2:2;// 10 - содержит специальное численное значение

//unsigned char pr3:2;// 11 - регистр пуст

//unsigned char pr4:2;

//unsigned char pr5:2;

//unsigned char pr6:2;

//unsigned char pr7:2;

} data[8];

unsigned short int twr;

};

union ud16

{

bait_tab data[2];

short val;

};

union ud32

{

bait_tab data[4];

 int val;

};

union ud64

{

bait_tab data[8];

 _int64 val;

};

struct ud80

{

ud64 mant;

ud16 exp;

};

union str

{

bait_tab data[10];

ud80 val;

};

int fld(str reg[],_sreg &sreg,_creg creg,_twr twr,int st0 ,int stimm);

int print_st(str reg[],_sreg sreg,_creg creg,_twr twr,int id);

int fsub(str reg[],_sreg &sreg,_creg creg,_twr twr,int fl,int s1, int s2);

int main()

{

str reg[9]={};

_sreg sreg;

_creg creg;

_twr twr;

setlocale(LC_ALL,"Russian");

int d = -1;

sreg.sreg = 0;

creg.creg = 0;

sreg.data.TOP = 7;

creg.data.PC = 3;

twr.twr = 0xffff;

memset(reg,0,sizeof(reg));

while(d != 0)

{

printf("1 - fsub\n2 - fsub n\n3 - fsub st(n), st(n)\n4 - fld\n0 - выход\n");

scanf("%d",&d);

switch (d)

{

case 1:// fsub========================================================================================

fsub(reg,sreg,creg,twr,1,0,0);

//print_st(reg,sreg,creg,twr,0);

break;

case 2:

printf("Введите непосредственный операнд: \n");

fld(reg,sreg,creg,twr,0,9);

print_st(reg,sreg,creg,twr,0);

break;

case 3:

int s1;

int s2;

printf("Введите номера регистров, которые вы хотите использовать: \n");

scanf("%d %d",&s1,&s2);

//fld(reg,sreg,creg,twr,s1,0);

//fld(reg,sreg,creg,twr,s2,0);

fsub(reg,sreg,creg,twr,1,s1,s2);

break;

case 4:

printf("Добовлнение значения в стек: \n");

fld(reg,sreg,creg,twr,0,0);

break;

}

}

}

int fld(str reg[],_sreg &sreg,_creg creg,_twr twr,int st0 ,int stimm)

{

short p = 0;

char l[10];

_int64 i = 0;

scanf("%s",&l);

for(int m = 0; m <= strlen(l); m++)

{

if ((l[m] == '0')&&(p <= 0))

{

p--;

}

else

{

if ((i == 0)&&(l[m] != ','))p++;

}

if (l[m] == ',')

{

for(int e = m; e < strlen(l); e++)

{

l[e] = l[e+1];

}

char* ends;

i = strtol(l,&ends,10);

if (l[m] != '0')break;

}

}

/*if (p > 0)

{p++;}

else

{p--;}*/

if (i != 0)

{

twr.data[st0].pr0 &= 0;

}

else

{twr.data[st0].pr0 |= 1;}

p--;

if (stimm == 0)

{

if (st0 != 0)

{

reg[st0].val.mant.val = i;

reg[st0].val.exp.val = p;

}

else

{

reg[sreg.data.TOP].val.mant.val = i;

reg[sreg.data.TOP].val.exp.val = p;

sreg.data.TOP =sreg.data.TOP - 1;

}

}

else

{

reg[8].val.mant.val = i;

reg[8].val.exp.val = p;

fsub(reg,sreg,creg,twr,2,0,0);

}

return 0;

}

int print_st(str reg[],_sreg sreg,_creg creg,_twr twr, int id)

{

int ssn;

if (id != 0)

{

ssn = id;

}

else

{

ssn = sreg.data.TOP;

}

double a = (double)reg[ssn].val.mant.val;

short b = reg[ssn].val.exp.val;

for (int i = 0; i <= abs(b); i++)

{

a /=10;

}

printf("%10.5f\n",a);

return 0;

}

int fsub(str reg[],_sreg &sreg,_creg creg,_twr twr,int fl, int s1,int s2)

{

_int64 a;

short am;

_int64 b;

short bm;

int sn1;

int sn2;

if (fl == 1)

{

if ((s2 == 0)&&(s1 == 0))

{

//sn1 = sreg.data.TOP + 2;

//sn2 = sreg.data.TOP + 1 ;

sn1 = 7;

sn2 = 6;

}

else

{

sn1 = sreg.data.TOP + s1;

sn2 = sreg.data.TOP + s2;

}

 a = reg[sn1].val.mant.val;

 am = reg[sn1].val.exp.val;

 b = reg[sn2].val.mant.val;

 bm = reg[sn2].val.exp.val;

}

else

{

a = reg[sreg.data.TOP +1].val.mant.val;

am = reg[sreg.data.TOP +1].val.exp.val;

b = reg[8].val.mant.val;

bm = reg[8].val.exp.val;

}

short dm = am - bm;

if (a > b)

{

for(int i = 0; i < dm; i++)

{

a *= 10;

}

//reg[sn1].val.exp.val+=dm;

}

else

{

for(short n = 0; n <= (-1)*dm; n++)

{

b *= 10;

}

if (fl == 1)

{

reg[sn1].val.exp.val += (-1)*dm;

}

else

{

reg[sreg.data.TOP +1].val.exp.val += (-1)*dm;

}

}

a-= b;

//printf("%d\n",a);

if (fl == 1)

{

reg[sn1].val.mant.val = a;

//sreg.data.TOP+=2;

print_st(reg,sreg,creg,twr,sn1);

}

else

{

reg[sreg.data.TOP].val.mant.val = a;

//sreg.data.TOP+=1;

}

return 0;

}


Информация о работе «Эмуляция команды математического сопроцессора FSUB»
Раздел: Информатика, программирование
Количество знаков с пробелами: 27839
Количество таблиц: 21
Количество изображений: 6

Похожие работы

Скачать
181295
4
0

... изменения сегмента (Segment Override). В системе команд насчитывается несколько сотен инструкций, поэтому в данной работе обзорно рассмотрены все команды обработки данных (блоков процессора АЛУ, FPU, MMX, и XMM), а далее более подробно описаны инструкции, появившиеся в процессорах Pentium 3 (блок XMM — SSE) и Pentium 4 (блок XMM — SSE2). Инструкции пересылки данных (см. табл) позволяют ...

Скачать
668870
13
0

... программе. В данном разделе они перечислены в алфавитном порядке и приводятся с объяснениями. Эти ошибки могут являться следствием случайного затирание памяти программой. Abnormal program termination Аварийное завершение программы Данное сообщение может появляться, если для выполнения программы не может быть выделено достаточного количества памяти. Более подробно оно рассматривается в конце ...

0 комментариев


Наверх