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

Второй пример использования сопроцессора 8087 гораздо глубже

раскрывает перед нами его работу.Этот пример - подпрограмма,

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

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

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

десяти в степени X.Исходный текст этой подпрограммы приведен на

Фиг. 7.24.

Сопроцессор 8087 не имеет команды возведения 10 в произвольную

степень, но мы можем возводить в любую степень двойки.Поэтому

нужжно пользоваться формулой

 

10**X = 2**(X*Log2(10))

 

Первые две команды программы формируют показатель степени двух.

Программа загружает константу Log210, а затем умножает ее на

исходное число X, давая необходимую степень 2, называемую здесь E.

Поле комментариев в примере используется для иллюстрации элементов

стека сопроцессора 8087.Символ "?" означает, что значение

Microsoft (R) Macro Assembler Version 5.00 1/1/80 04:04:40

Фиг. 7.24 Вычисление 10**STPage1-1

 

PAGE,132

TITLEФиг. 7.24 Вычисление 10**ST

0000CODESEGMENT PUBLIC

ASSUMECS:CODE,DS:CODE

PUBLICTEN_TO_X

0000????OLD_CWDW?

0002????NEW_CWDW?

;--------------------------------------------

; Эта программа извлекает число с вершины стека

;сопроцессора 8087 и возводит 10 в эту степень.

; Параметры: X в ST(0)

; Результат: 10**X в ST(0)

; Эта программа использует две ячейки в стеке 8087

;плюс параметр - всего три ячейки.

;--------------------------------------------

0004TEN_TO_XPROCNEAR

;----ST(0)------;-----ST(1)-----;--ST(2)--

; X; ?; ?

00049B D9 E9FLDL2T; LOG2(10); X; ?

00079B DE C9FMULPST(1),ST(0); X*LOG2(10)=E; ?; ?

000AD9 3E 0000 RFNSTCWOLD_CW;---------------;---------------;--------

000E9B FWAIT; Выборка текущего слова состояния

000FA1 0000 RMOVAX,OLD_CW; Сохранение слова сотояния

001225 F3FFANDAX,NOT 0C00H; Установка способа округления к минус

00150D 0400ORAX,0400H;бесконечности

0018A3 0002 RMOVNEW_CW,AX

001B9B D9 2E 0002 RFLDCWNEW_CW;---------------;---------------;--------

00209B D9 E8FLD1; 1; E; ?

00239B D9 E0FCHS; -1; E; ?

00269B D9 C1FLDST(1); E; -1; E

00299B D9 FCFRNDINT; INT(E) = I; -1; E

002C9B D9 2E 0000 RFLDCWOLD_CW; ; ;

00319B D9 CAFXCHST(2); E; -1; I

00349B D8 E2FSUBST(0),ST(2); E - I = F; -1; I

00379B D9 FDFSCALE; F*2**-1 = F/2 ; -1; I

003A9B D9 F0F2XM1; (2**F/2)-1; -1; I

003D9B DE E1FSUBRPST(1),ST(0); 2**F/2; I; ?

00409B D8 8E 0000 UFMULST(0); 2**F; I; ?

00459B D9 FDFSCALE; (2**F)*(2**I) ; I; ?

00489B D9 C9FXCHST(1); I; 2**(I+F); ?

004B9B D8 D9FCOMP; 2**(I+F); ?; ?

004EC3 RET; 10**X; ?; ?

004FTEN_TO_XENDP

004FCODEENDS

END

 

Фиг. 7.24 Вычисление 10**ST

 

соответствующего элемента стека неопределено.В подпрограмме

используется всего три элемента стека, так что в поле комментариев

есть три колонки.

Хотя теперь мы имеем нужную степень двух, у сопроцессора 8087

отсутствует команда, завершившая бы всю работу за один шаг.

Команда F2XM1 возводит 2 в степень X, но только если X меньше или

равен 1/2.Это означает, что степень E мы должны разделить на

целую и дробную части; затем команда FSCALE сможет возвести 2 в

целую степень, а команда F2XM1 обработает дробную часть.

 

Перед разделением E на две части программа выполняет некоторые

вспомогательные действия.Эти действия - команды сопроцессора

8087, которые читают управляющее слово и устанавливают режим

округления в направлении меньшего числа.Теперь, когда мы возьмем

целую часть показателя степени, его значение будет округляться

влево, в направлении минус бесконечности.Дробная часть показателя

будет положительным числом, что также требуется для команды F2XM1.

 

Обратите внимание на использование команды FWAIT после команды

FNSTCW.Ожидать окончания выполнения умножения перед записью

управляющего слова не надо, так как умножение не меняет код в

управляющем слове.Но перед чтением управляющего слова из главной

памяти и модификацией его нужна гарантия, что сопроцессор 8087 уже

завершил запись.Значит, нужно выполнить команду ожидания FWAIT

перед чтением.

 

После установки способа округления команда FRNDINT округляет

показатель степени E до целого значения.Так как мы также

запомнили и исходное значение E в стеке, можно вычесть целую часть

из E и получить дробную часть показателя степени.То есть теперь E

= I + F, и можно записать

 

2**E = 2**I*2**F

 

Но перед тем обратим внимание на одну маленькую деталь.

Дробная часть F может оказаться значением большим 1/2, и поэтому не

может быть аргументом команды F2XM1.Сейчас мы используем число

-1, ранее помещенное в стек, чтобы разделить F на 2, получив при

этом F/2.Чтобы это сделать, воспользуемся командой FSCALE, так

как эта команда умножает содержимое ST0 на 2 в степени,

содержащейся в ST1.Поскольку в элементе ST1 содержится -1,

результирующим эффектом будет умножение на 1/2.Теперь можно

утверждать, что содержимое регистра ST0 меньше 1/2.

 

Далее команда F2XM1 возводит 2 в степень F/2, а -1 в стеке

помогает ликвидировать -1, порождаемую в результате работы команды

F2XM1.Обратное вычитание с извлечением из стека избавляется и от

-1 в стеке.Затем 2F/2 умножается само на себя, в элементе ST0

получается число 2F.Так как целая часть показателя степени теперь

переместилась в элементе ST1, команда FSCALE умножает 2I на число

2F, которое уже находится в элементе ST0, давая искомый результат.

Команда FCOMP удаляет из стека число I перед возвратом из

подпрограммы.


 

Mail.ru