На главную Назад
Добро пожаловать, уважаемый посетитель!

Последний пример использования сопроцессора 8087 - вычисление

синуса угла.У сопроцессора 8087 нет команды вычисления функции

SIN; самое большее, что он может - это выполнить команду FPTAN,

нахождение частичного тангенса.Чтобы выполнить операцию SIN,

воспользуемся этой командой, а также командой FPREM (частичный

остаток).

 

Программа, вычисляющая SIN, показана на Фиг. 7.27.Эта

программа вычисляет и печатает синусы углов от 1/2 до 6 с шагом 1/2

радиана.Выдача программы аналогична выдаче следующей программы на

языке Бейсик:

 

10FOR X = .5 TO 6.0 STEP .5

20PRINT SIN(X)

30NEXT X

 

Для печати результатов используется подпрограмма на Фиг. 7.25.

 

Microsoft (R) Macro Assembler Version 5.001/1/80 04:05:01

Фиг. 7.27 Вычисление синуса угла Page1-1

 

 

PAGE,132

TITLEФиг. 7.27 Вычисление синуса угла

 

0000STACKSEGMENT STACK

00000040[DW64 DUP (?)

????

]

 

0080STACKENDS

0000CODESEGMENT

ASSUMECS:CODE,DS:CODE,ES:CODE

EXTRNFLOAT_ASCII:NEAR

00000001NUM_ANGLEDW1

00020002DEN_ANGLEDW2

0004????STATUSDW?

00060004FOURDW4

= 0040C3EQU40H

= 0004C2EQU04H

= 0002C1EQU02H

= 0001C0EQU01H

000893 A3 AE AB 20 E1 ABERROR_MSGDB'Угол слишком большой', 10, 13, '$'

A8 E8 AA AE AC 20 A1

AE AB EC E8 AE A9 0A

0D 24

001FSINPROCFAR

001F1EPUSHDS

00202B C0SUBAX, AX

002250PUSHAX

00238C C8MOVAX, CS

00258E D8MOVDS, AX

00278E C0MOVES, AX

0029DO_AGAIN:

00299B DB E3FINIT;-----ST(0)-----;-----ST(1)------

002C9B DF 06 0000 RFILDNUM_ANGLE;;

00319B DE 36 0002 RFIDIVDEN_ANGLE; X = Угол;

 

Фиг. 7.27 (a) Процедура SIN (начало)

00369B D9 EBFLDPI; PI; X

00399B DE 36 0006 RFIDIVFOUR; PI/4; X

003E9B D9 C9FXCH; X; PI/4

00419B D9 F8FPREM; R; PI/4

00449B DD 3E 0004 RFSTSWSTATUS

00499BFWAIT

004A8A 26 0005 RMOVAH, BYTE PTR STATUS+1

004EF6 C4 04TESTAH, C2

005175 55JNZBIG_ANGLE

0053F6 C4 02TESTAH, C1; Определяется, необходимо ли вычитание PI/4

005674 05JZDO_R; Если 0, то не необходимо вычитание PI/4

00589B DE E1FSUBRPST(1), ST(0); A = PI/4-R; ?

005BEB 06JMPSHORT DO_FPTAN

005DDO_R:

005D9B D9 C9FXCH; PI/4; R

00609B D8 D9FCOMP; R; ?

0063DO_FPTAN:

00639B D9 F2FPTAN; OPP; ADJГде OPP/ADJ=Tan(A)

 

;-----Опеределение того, что нужно - синус или косинус

 

0066F6 C4 42TESTAH, C3 or C1

00697A 03JPEDO_SINE

006B9B D9 C9FXCH; ADJ; OPP

006EDO_SINE: ; D; N

 

;-----Вычисление N/SQR(N**2 + D**2)

006E9B D8 8E 0000 UFMULST(0); D**2; N

00739B D9 C9FXCHST(1); N; D**2

00769B D9 C0FLDST(0); N; N; D**2

00799B D8 8E 0000 UFMULST(0); N**2; N; D**2

007E9B DC 06 0000 UFADDST(2); N**2 + D**2; N; D**2

00839B D9 FAFSQRT; SQR(N2 + D2); N; D**2

00869B DE F1FDIVRPST(1); SIN(X); D**2

00899B D9 C9FXCHST(1); D**2; SIN(X)

008C9B D8 D9FCOMP; SIN(X); ?

008FF6 C4 01TESTAH, C0

009274 03JZSIGN_OK

00949B D9 E0FCHS

0097SIGN_OK:

0097E8 0000 E CALLFLOAT_ASCII

009AFF 06 0000 RINCNUM_ANGLE

009E83 3E 0000 R 0DCMPNUM_ANGLE, 13

00A377 02JARETURN_INST

00A5EB 82JMPDO_AGAIN

00A7RETURN_INST:

00A7CBRET

00A8BIG_ANGLE:

00A88D 16 0008 RLEADX, ERROR_MSG

00ACB4 09MOVAH, 9H

00AECD 21INT21H

00B0CBRET

00B1SINENDP

00B1CODEENDS

ENDSIN

Фиг. 7.27 (a) Процедура SIN (продолжение)

A>SIN

4.79425539E-001

8.41470985E-001

9.97494987E-001

5.98472144E-001

1.41120008E-001

-3.50783228E-001

-7.56802495E-001

-9.77530118E-001

-9.58924275E-001

-7.05540326E-001

-2.79415498E-001

2.15119988E-001

 

Фиг. 7.27 (b) Вывод процедуры SIN

 

Фиг. 7.27 Вычисление синуса угла

 

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

в качестве файла типа .EXE.Затем сопроцессор 8087 загружает два

целых числа и делит их, формируя исходный угол.Это - пример

использования двух целых чисел для порождения числа с плавающей

точкой (в данном случае 1/2), что нельзя сделать непосредственно с

помощью ассемблера.

 

Как вы помните из тригонометрии, синус - периодическая функция.

То есть функция дает один и тот же результат в случае исходных

чисел, различающихся ровно на 2*PI.Поэтому первой задачей

подпрограммы SIN является замена исходного угла соответствующим

значением, лежащим в диапазоне

 

0 <= X < 2*PI

 

В команде FPTAN требуется, чтобы угол находился в диапазоне

 

0 <= X < PI/4

 

Это означает, что даже если угол и меньше 2*PI, мы должны

уменьшить его еще, чтобы он удовлетворял ограничениям команды

FPTAN.К счастью, если исходный угол уменьшен до значения,

меньшего PI/4, все еще можно определить верное значение

тригонометрических функций.Чтобы это сделать, надо знать, в каком

месте исходного диапазона от 0 до 2*PI находился исходный угол.

 

Нужное уменьшение угла выполняет команда FPREM.Она не только

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

течение процесса поиска остатка.Эти три бита команда записывает в

слово состояния.Следовательно, хотя мы и уменьшили угол до

значения одной восьмой исходного диапазона, все же можно определить

октант, в который попадет угол.Зная его, можно найти формулу

вычисления синуса с помощью тригонометрических преобразований.

Таблица на Фиг. 7.28 показывает связь между исходным октантом и

методом вычисления синуса угла.В таблице предполагается, что

число R - это остаток от уменьшения исходного угла до значения

меньше PI/4.Номер октанта появляется в разрядах C3 = C1 = C0

после выполнения команды FPREM.

 

С помощью этой таблицы мы можем определить формулу вычислений,

применяемую в каждом случае выполнения программы.После загрузки

значения угла в радианах программа загружает число и делит его на

4, чтобы использовать в команде FPREM.В этот момент

"захватывается" слово состояния.Если процесс поиска остатка не

завершился на этом единственном шаге, это означает, что исходный

угол был больше 2**64.Следовательно, его значение настолько больше

максимально возможного при вычислениях тригонометрических функций,

что мы отбрасываем это число, как слишком большое.Этого не

происходит со значениями, выбранными в примере, но здесь для

иллюстрации введена такая проверка.

 

Октанты

C0C3C1ДиапазонSIN(X) = :

-----------------------------------------------------

0 0 00PI/4SIN(R)

0 0 1PI/4PI/2COS(PI/4-R)

0 1 0PI/23*PI/4COS(R)

0 1 13*PI/4PISIN(PI/4-R)

1 0 0PI5*PI/4- SIN(R)

1 0 15*PI/43*PI/2- COS(PI4-R)

1 1 03*PI/27*PI/4- COS(R)

1 1 17*PI/42*PI- SIN(PI/4-R)

 

(R - остаток, 0<R<PI/4)

-----------------------------------------------------

 

Фиг. 7.28 SIN(X) в восьми секторах

 

Программа проверяет разряд C1 в регистре состояния, чтобы

определить, должна ли она использовать остаток R, или его надо

вычесть из PI/4.Так как PI/4 еще находится в одном из регистров,

это сделать просто.Если вычитание не требуется, команда FCOMP

удаляет из стека ненужное значение PI/4.

 

Затем команда FPTAN вычисляет частичный тангенс.Результат

работы команды показан, как OPP/ADJ (сокращения от английских слов

Opposite (противоположный) и Adjacent (соседний)), что равно

тангенсу угла R или PI/4-R, в зависимости от того, что было

выбрано.С помощью этих двух чисел теперь можно опеределить синус

или косинус угла.Например, синус, заданный парой чисел OPP/ADJ,

можно вычислить по формуле

 

SIN(X) = OPP/SQR(OPP**2+ADJ**2), где TAN(X) = OPP/ADJ

 

Чтобы вычислить косинус, нужно числитель заменить на ADJ.Мы

решаем, нужен ли синус или косинус, анализируя запомненные

описатели октанта, т.е.проверяя значения разрядов C3 и C1.

Команда TEST выделяет эти значения, а команда JPE делает переход,

если они оба нулевые или оба единичные.В этом случае мы вычисляем

синус; если же они различны, мы вычисляем косинус, что достигается

заменой местами значений OPP и ADJ в стеке регистров.

 

Далее следующие команды сопроцессора 8087 вычисляют значение

синуса (или косинуса) по значению частичного тангенса.

Единственный шаг, который еще надо выполнить - это определение

окончательного знака результата.В случае синуса результат

отрицателен, если угол находится в октантах от четвертого до

седьмого.Проверка разряда C0 определяет верный знак результата.

Затем программа FLOAT_ASCII, показанная на Фиг. 7.25, печатает

число в плавающем формате.Управление возвращается назад, к началу

цикла, если еще не пройдены все октанты.Нижняя часть Фиг. 7.27

иллюстрирует результат выполнения этой программы.


 

Mail.ru