Команды сравнения
Команды сравнения
Как и в наборе команд микропроцессора 8088, у сопроцессора 8087
есть команды, сравнивающие два числа. Сопроцессор 8087 отбрасывает
результат сравнения, но устанавливает в соответствии с ним флаги
состояния. Перед тем как опросить флаги состояния, программа
должна считать слово состояния в память. Далее проще всего
загрузить флаги состояния в регистр AH, а затем, для легкости
проверки условия, - в регистр флагов макропроцессора 8088.
На Фиг. 7.18 показан листинг ассемблера команд сравнения
сопроцессора 8087. Так как в операции всегда участвует вершина
стека, в программе надо указать только один регистр или операнд в
памяти. После сравнения в слове состояния содержится информация о
соотношении двух чисел. Таблица на Фиг. 7.19 показывает возможные
варианты соотношений. Для отражения результата сравнения
необходимы только два бита состояния - C3 и C0; расположение C3 и
C0 в слове состояния показано на Фиг. 7.8.
На Фиг. 7.20 приведен фрагмент программы, которая сравнивает
содержимое вершины стека и слово в памяти. Переходы в этой
программе выполняются на основе результата сравнения. В одном из
четырех случаев числа нельзя сравнить. Это происходит тогда, когда
одно из чисел есть NAN (не число) или одна из форм бесконечности.
Microsoft (R) Macro Assembler Version 5.00 1/1/80 04:04:18
Фиг. 7.18 Команды сравнения сопроцессора 8087 Page 1-1
PAGE ,132
TITLE Фиг. 7.18 Команды сравнения сопроцессора 8087
0000 CODE SEGMENT
ASSUME CS:CODE,DS:CODE
0000 WORD_INTEGER LABEL WORD
0000 SHORT_INTEGER LABEL DWORD
0000 SHORT_REAL LABEL DWORD
0000 LONG_REAL LABEL QWORD
0000 9B D8 D1 FCOM
0003 9B D8 D2 FCOM ST(2)
0006 9B DE 16 0000 R FICOM WORD_INTEGER
000B 9B D8 16 0000 R FCOM SHORT_REAL
0010 9B D8 D9 FCOMP
0013 9B DA 1E 0000 R FICOMP SHORT_INTEGER
0018 9B DC 1E 0000 R FCOMP LONG_REAL
001D 9B DE D9 FCOMPP
0020 9B D9 E4 FTST
0023 9B D9 E5 FXAM
0026 CODE ENDS
END
Фиг. 7.18 Команды сравнения сопроцессора 8087
Сопроцессор 8087 помещает флаги состояния C3 и C0 в точности на те
же места, которые в регистре флагов микропроцессора 8088 занимают
флаги нуля C3 и переноса C0. Как показано на рисунке, если
программа переслала старший байт слова состояния сопроцессора 8087
в регистр флагов микропроцессора 8088, она может выполнить условный
переход с помощью непосредственной проверки состояния флагов с
использованием команды условного перехода, и не нужно выделять и
проверять отдельные биты слова состояния.
С3 С0 Порядок
--------------------------------------------------------------
0 0 ST > источник
0 1 ST < источник
1 0 ST = источник
1 1 ST и источник несравнимы
--------------------------------------------------------------
Фиг. 7.19 Порядок сравнения
На Фиг. 7.18 демонстрируется, что существуют и другие варианты
команды FCOM, в том числе и то, что для команды FCOM существует
версия FICOM необходимая для ставнения целых чисел. Команды FCOMP
и FICOMP идентичны командам FCOM и FICOM, за исключением того, что
сопроцессор 8087 извлекает из стека содержимое вершины после
выполнения операции. Это позволяет сравнить два числа с помощью
сопроцессора 8087, не беспокоясь о том, что нужно удалить из стека
первый операнд после операции.
Microsoft (R) Macro Assembler Version 5.00 1/1/80 04:04:23
Фиг. 7.20 Условный переход Page 1-1
PAGE ,132
TITLE Фиг. 7.20 Условный переход
0000 CODE SEGMENT
ASSUME CS:CODE,DS:CODE
0000 WORD_INTEGER LABEL WORD
0000 ???? STATUS_WORD DW ?
;----- Сравнивается WORD_PTR со словом на вершине стека сопроцессора 8087
0002 9B DE 16 0000 R FICOM WORD_INTEGER ; Сравнение слова с ST
0007 9B DD 3E 0000 R FSTSW STATUS_WORD ; Сохранение слова состояния 8087
000C 9B FWAIT ; Синхронизация процессора с сопроцессором
000D 8A 26 0001 R MOV AH,BYTE PTR STATUS_WORD+1
0011 9E SAHF ; Занесение флагов (C0=CF,C3=ZF)
0012 72 02 JB CONTINUE ; Проверка флага C0,переход если 0
0014 75 00 JNE ST_GREATER ; Проверка флага C3
0016 ST_EQUAL: ; Попадаем сюда,если C3=1,C0=0 -
; ... ; значения равны
0016 ST_GREATER: ; Попадаем сюда,если C3=0,C0=0 - число
; ... ; на вершине стека 8087 больше WORD_PTR
0016 CONTINUE:
0016 75 00 JNE ST_LESS ; Проверка флага C3
0018 UNORDERED: ; Попадаем сюда,если C3=1,C0=1 - невоз-
; ... ; можно определить какое из чисел больше
0018 ST_LESS: ; Попадаем сюда,если C3=0,C0=1 - число
; ... ; на вершине стека 8087 меньше WORD_PTR
0018 CODE ENDS
END
Фиг. 7.20 Условный переход
У команды FCOMPP программист не указывает никаких операндов.
Эта команда всегда сравнивает верхние два элемента стека. После
сравнения они оба исчезают из стека.
Команды сравнения с извлечением из стека обеспечивают удобный
способ очистки стека. Поскольку у сопроцессора 8087 нет команды,
удобно извлекающей операнд из стека, вместо нее можно использовать
команды сравнения с извлечением из стека. Эти команды также
изменяют и регистр состояния, и их нельзя использовать, если биты
состояния имеют значение для дальнейшей работы, но в большинстве
случаев эти команды позволяют быстро извлечь из стека один или два
операнда. Так как сопроцессор 8087 регистрирует ошибку при
переполнении стека, необходимо удалить все операнды из стека при
окончании вычислений.
Существуют две специальные команды сравнения. Команда
сравнения содержимого вершины стека с нулем FTST, с помощью которой
можно быстро определить знак содержимого вершины стека. (Результат
сравнения иллюстрируется таблицей на Фиг. 7.19, нужно только всюду в
таблице слово "источник" заменить на слово "нуль").
Команда FXAM, строго говоря, не является командой сравнения.
Хотя она и работает с содержимым вершины стека, но не сравнивает
содержимое вершины ни с одним другим числом. Скорее команда FXAM
устанавливает все четыре флага регистра состояния (от C3 до C0
включительно), показывая, какого типа число находится в вершине
стека. Так как сопроцессор 8087 может обрабатывать любые формы
чисел, а не только нормализованные числа с плавающей точкой,
команда FXAM определит, что же находится в вершине стека. На
Фиг. 7.21 показаны значения битов состояния в каждом случае.
Если при арифметической обработке вы не делаете что=либо из
ряда вон выходящее и не работаете на пределе разрядной сетки
сопроцессора 8087, то не нужно рассматривать никакие из приведенных
выше результатов команды FXAM; вы должны ожидать увидеть лишь
положительные либо отрицательные нормализованные числа или нули.
Если выясняется, что вершина стека пустая, то обычно выдается
ошибка. Программа может сделать такую проверку для контроля
параметра, переданного в вершине стека.
Остальные значения - это реакция микросхемы 8087 на ошибку.
Когда сопроцессор 8087 обнаруживает ошибку, он пытается возбудить
прерывание по особой ситуации, устанавливая соответствующие биты в
слове состояния. Однако если ситуация замаскирована с помощью
управляющего слова, сопроцессор 8087 сам реагирует на нее. Он
решает, какая реакция соответствует данной ошибке и возбуждает
появление специфического числа в регистре. Например, результат NAN
возникает, если операция некорректна, как в случае извлечения
квадратного корня из отрицательного числа. Бесконечность
появляется, если результат операции слишком велик для представления
с плавающей точкой.
C3 C2 C1 C0 Значение С3 С2 С1 С0 Значение
---------------------------------------------------------------------------------------------------
0 0 0 0 + Ненормально 1 0 0 0 + 0
0 0 0 1 + NAN 1 0 0 1 Пусто
0 0 1 0 - Ненормально 1 0 1 0 - 0
0 0 1 1 - NAN 1 0 1 1 Пусто
0 1 0 0 + Нормально 1 1 0 0 + Ненормальное
0 1 0 1 + Бесконечность 1 1 0 1 Пусто
0 1 1 0 - Нормально 1 1 1 0 - Ненормальное
0 1 1 1 - Бесконечность 1 1 1 1 Пусто
---------------------------------------------------------------------------------------------------
Фиг. 7.21 Пример интерпретации кодов состояний
Денормализованные и ненормализованные числа возникают при
достижении другого предела представления чисел с плавающей точкой.
Когда число становится настолько маленьким, что у него уже нет
смещенного порядка, оно становится денормализованным. Вместо того,
чтобы заменить число нулем, процессор 8087 записывает наименьшее
значение порядка и ненормализованную мантиссу. Это означает, что
число теряет точность, так как у его мантиссы появляются незначащие
нули. Но денормализованный результат все же точнее, чем просто
нуль. И это тот случай, при котором сопроцессор 8087, продолжая
работу, наилучшим образом реагирует на плохие условия. Пометка
числа, как денормализованного, должна насторожить вас. При этом
также устанавливается бит денормализации в регистре особых
ситуаций, и остается установленным до тех пор, пока команда FCLEX
не сбросит биты особых ситуаций. С помощью анализа флагов
программа может зарегистрировать возникновение ошибки и отнестись к
результатам с подозрением.