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

Этот раздел главы с помощью примеров исполльзования наиболее

распространенных операций научит вас применять сопроцессор 8087,

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

т.е.в них не делается попыток обработки всех возможных ошибок или

реакции на какие=либо специальные числа, с которыми может работать

микросхема 8087.Сопроцессор 8087, конечно же, имеет такие

возможности, но эти действия относятся к более сложным.Когда вы

освоите основы техники, вы сможете добавить к этим примерам

некоторые фрагменты, которые превратят их в настоящие подпрограммы

общего назначения.

Первый пример - исходный текст программы на Фиг. 7.23.Эта

программа распечатывает короткое действительное представление

степеней 10 от 103 до 1039.Как мы уже видели в разделе,

посвященном представлению данных, Макроассемблер фирмы IBM не имеет

возможностей непосредственно генерировать действительные числа.

Наличие такой таблицы чисел облегчит вам представление в виде

констант степеней 10.По этой таблице вы сможете определить

шестнадцатеричное представление числа, которое нужно использовать в

программе.

 

Программа вычисляет только каждую третью степень 10, и

использует короткий действительный формат.Если вы работаете с

много большими числами, или вам нужна большая точность, тогда нужно

выполнить этот пример, используя длинный действительный формат

чисел, а также построить каждую степень 10.Выполните это в

качестве упражнения.

 

Первоочередная цель этого примера - введение в программирование

и работу на сопроцессоре 8087.Это отдельная самостоятельная

программа, предназначенная для выполнения в виде файла типа .EXE.

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

сегмент STACK, необходимый в файле типа .EXE.Сначала в сегменте

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

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

увидите, что первой выполняемой командой будет команда, помеченная

CALCULATE_POWER, так как она указана в операторе END.

 

Первая часть программы выполняет инициализацию.Перед

загрузкой указателя на сегмент CODE в регистр DS программа помещает

в стек адрес возврата из файла типа .EXE.Затем с помощью команды

FINIT инициализируется сопроцессор 8087, что аналогично аппаратному

сбросу.Тем самым сопроцессор 8087 оказывается настроенным на

обработку особых ситуаций по умолчанию, что наилучшим образом

подходит для примеров этой книги.Команда FINIT также сбрасывает

регистровый стек сопроцессора 8087, освобождая все его восемь

позиций.Программа должна использовать команду FINIT только в

момент запуска.Команда FINIT никогда не должна быть использована

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

 

Следующие команды загружают число 1000 в регистр ST1 и число 1

в регистр ST0.Все следующие команды сопроцессора 8087 используют

эти два регистра стека.В регистре ST0 находится текущая степень

десяти, а в регистре ST1 находится значение 103.Мы будем

использовать число в регистре ST1 для увеличения числа в регистре

ST0 после каждой итерации программы.Целая переменная POWER

содержит текущую степень 10, находящуюся в регистре ST0.

 

После метки POWER_LOOP элемент ST0 умножается на элемент ST1,

(в котором содержится число 1000), чтобы увеличить содержимое

регистра ST0 в 103 раз.Команда FST записывает результат в память.

Оставшаяся часть программы после метки POWER_LOOP печатает

результаты вычислений.В подпрограмме TRANSLATE шестнадцатеричный

байт преобразуется в двухбайтовую строку в коде ASCII так, что

программа может его распечатать.Текущее значение POWER (степень

десяти), а также шестнадцатеричная строка, записанная процессором

8087, преобразуются в код ASCII.Затем функция DOS печатает строку

на дисплее.Цикл POWER_LOOP продолжается до тех пор, пока

последнее напечатанное значение не станет больше 1038.Это

значение выбрано потому, что 1038 - это максимальное число, которое

может быть представлено в коротком действительном формате.Если бы

использовался длинный действительный формат чисел, это значение

было бы равно 10308.Заключительная часть Фиг. 7.23 показывает,

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

 

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

Фиг. 7.23 Степени 10 Page1-1

 

 

PAGE,132

TITLEФиг. 7.23 Степени 10

 

0000STACKSEGMENT STACK

00000040[DW64 DUP (?)

????

]

 

0080STACKENDS

 

0000CODESEGMENT

ASSUMECS:CODE

 

0000????????POWER_OF_TENDD?; Область данных для 10**x,

;короткое плавающее

00040002[OUTPUT_POWERDB2 DUP (' '); Текстовый буфер для значения

20

]

 

000648 20 20 20 20DB'H';степени

000B0008[OUTPUT_STRINGDB8 DUP (''); Текстовый буфер для результата -

20 20 20 20 20

20 20 20 20

]

005348 0D 0A 24 DB'H',13,10,'$'; Конец строки

005700POWERDB0; Текущая степень 10

005803E8THOUSANDDW1000; Константа

005A03BFCONTROL_87DW03BFH

 

005CCALCULATE_POWER PROCFAR

005C1EPUSHDS ; Занесение в стек адреса возврата

005DB8 0000MOVAX, 0

006050PUSHAX

00610EPUSHCS

00621FPOPDS

ASSUMEDS:CODE; Адресация области данных

00639B DB E3FINIT; Инициализация сопроцессора 8087

 

Фиг. 7.23 (а) (начало)

00669B DF 06 0058 RFILDTHOUSAND; Загрузка 10**3 в стек сопроцессора 8087

006B9B D9 E8FLD1; Загрузка начального значения в стек 8087

006EPOWER_LOOP:

006E9B DC 8E 0000FMULST(1); Умножение ST(0) на ST(1)

00739B D9 16 0000 RFSTPOWER_OF_TEN; Сохранение в памяти результата

007880 06 0057 R 03ADDPOWER, 3; Увеличение показателя степени

007DA0 0057 RMOVAL, POWER; Выборка показателя степени

00808D 1E 0004 RLEABX, OUTPUT_POWER

0084E8 00AC RCALLTRANSLATE

0087B9 0004MOVCX, 4

008A8D 1E 000B RLEABX, OUTPUT_STRING

008E8D 36 0003 RLEASI, POWER_OF_TEN+3

0092FDSTD; Установка пересылки с уменьшением адреса

0093VALUE_OUTPUT:

 

0093ACLODSB; Выборка байта результата

0094E8 00AC RCALLTRANSLATE; Занесение символа в выводимую строку

0097E2 FALOOPVALUE_OUTPUT; Цикл по всем байтам результата

 

00998D 16 0004 RLEA DX, OUTPUT_POWER

009DB4 09MOVAH, 9H

009FCD 21INT21H

00A180 3E 0057 R 26CMPPOWER, 38

00A672 C6JBPOWER_LOOP

00A89B DE D9FCOMPP; Удаление из стека двух чисел

00ABCBRET

00ACCALCULATE_POWER ENDP

 

00ACTRANSLATEPROCNEAR

00AC50PUSHAX ; Сохранение исходного значения

00AD51PUSHCX

00AEB1 04MOVCL, 4; Сдвиг старшей цифры выводимого числа

00B0D2 E8SHRAL, CL;на место младшей цифры

00B259POPCX

00B3E8 00CB RCALLXLAT_OUTPUT; Вывод старшей цифры выводимого числа

00B658POPAX ; Восстановление младшей цифры

00B7E8 00CB RCALLXLAT_OUTPUT; Вывод младшей цифры выводимого числа

00BAC3RET

00BBTRANSLATEENDP

 

00BB30 31 32 33 34 35 36ASCII_TABLEDB'0123456789ABCDEF'

37 38 39 41 42 43 44

45 46

00CBXLAT_OUTPUTPROCNEAR

00CB24 0FANDAL, 0FH; Выделение младшей цифры

00CD53PUSHBX

00CE8D 1E 00BB RLEABX, ASCII_TABLE ; Адрес таблицы трансляции

00D2D7XLATASCII_TABLE; Преобразование в символьную форму

00D35BPOPBX

00D488 07MOV[BX], AL; Сохранение очередного символа результата

00D643INCBX ; Переключение на следующий символ

00D7C3RET

00D8XLAT_OUTPUTENDP

00D8CODEENDS

ENDCALCULATE_POWER

Фиг. 7.23 (а) (продолжение)

A>PRINT10

03H447A0000H

06H49742400H

09H4E6E6B28H

0CH5368D4A5H

0FH58635FA9H

12H5D5E0B6BH

15H6258D727H

18H6753C21CH

1BH6C4ECB8FH

1EH7149F2CAH

21H76453719H

24H7B4097CEH

27H7F800000H

 

Фиг. 7.23 (b)

 

Фиг. 7.23 (a) Степени 10; (b) Вывод процедуры степеней 10

 

Вам нужно посмотреть часть программы TRANSLATE, несмотря на то,

что она не использует ни одной команды сопроцессора 8087.Эта

часть - пример подготовки чисел к печати.В частности, команда

XLAT преобразует для печати шестнадцатеричную тетраду (значение от

0 до 0FH) в правильный символ кода ASCII (от 0 до F).Просто

прибавлять значение тетрады к значению 0 нельзя, так как в коде

ASCII символы от A до F не следуют непосредственно за символами от

0 до 9; преобразование прекрасно выполняет команда перекодировки.

Мы используем аналогичный метод, когда преобразуем число с

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


 

Mail.ru