Форум программистов, компьютерный форум, киберфорум
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.63/2256: Рейтинг темы: голосов - 2256, средняя оценка - 4.63
Ушел с форума
Автор FAQ
 Аватар для Mikl___
16374 / 7686 / 1080
Регистрация: 11.11.2010
Сообщений: 13,761
15.11.2013, 04:34  [ТС]
ГЛАВА 11
ДОПОЛНИТЕЛЬНЫЕ АРИФМЕТИЧЕСКИЕ КОМАНДЫ
Конструкторы микропроцессоров от i8080 до i80386 не смогли реализовать все математические функции на одном кристалле, так как это оказалось слишком сложным. Вместо этого они создали набор функций более низкого уровня, из которых можно программно построить любые математические функции. Вот так программист должен был вычислять, используя только операции сложения, вычитания и умножения, функции синуса, экспоненты или логарифма:
https://www.cyberforum.ru/cgi-bin/latex.cgi?sin(x)=x-\frac{x^3}{3!}+\frac{x^5}{5!}-...+(-1)^{n}\times \frac{x^{2n+1}}{(2n+1)!}
https://www.cyberforum.ru/cgi-bin/latex.cgi?e^{x}=1+\frac{x}{1!}+\frac{x^2}{2!}+...+\frac{x^{n}}{n!}
https://www.cyberforum.ru/cgi-bin/latex.cgi?ln(x)=(x-1)-\frac{(x-1)^2}{2}+\frac{(x-1)^3}{3}-...+(-1)^{n-1}\times\frac{(x-1)^{n}}{n}
Для обработки чисел с плавающей запятой в 1980 году компания Intel выпустила специальную микросхему i8087 – математический сопроцессор. Сопроцессор i8087 работал с первыми 16-разрядными микропроцессорами Intel 8086 и 8088. Основной микропроцессор и сопроцессор работали во взаимодействии друг с другом. Когда основной микропроцессор считывал специальную команду Esc (код от 0D8h до 0DFh), управление передавалось сопроцессору, который выполнял следующий за этой командой машинный код – одну из 68 команд для вычисления логарифма, тригонометрических функций, возведения в степень и т.д. Получив команду на выполнение, сопроцессор запускал набор собственных команд, записанных в ПЗУ. Обычно выполнение внутренних команд сопроцессора сопряжено с вычислением в цикле, поэтому основной микропроцессор в это время простаивал, ожидая получения результата от микропроцессора.
И все же, сопроцессор позволял ускорить вычисления, по сравнению с тем, если бы основному микропроцессору пришлось обрабатывать числа с плавающей запятой программным способом. Начиная с микропроцессора i80486 произошло объединение на одном кристалле математического сопроцессора с основным микропроцессором. Поэтому хватит вычислять значения синуса рядами, а воспользуемся командами, специально предназначенными для этого.
Каждый FPU (Floating Point Execute Unit – блок обработки чисел с плавающей запятой) имеет собственный набор команд и средства для выполнения операций с плавающей запятой, такие как экспоненциальные, логарифмические и тригонометрические функции. Блок FPU содержит восемь 80-битовых регистров (от ST(0) до ST(7)) для обработки чисел с плавающей запятой, которые могут представлять числовые значения до 10400.
Регистры данных блока FPU, в отличие от регистров общего назначения, не независимы, а организованы в стек, то есть операнды считываются в порядке, обратном их записи.
Использование команд блока FPU в антихакерских программах совсем недавно было предпочтительным потому, что хакерские программы были ориентированы на слежение за блоком IEU (Integer Execute Unit – блок целочисленной обработки), а действия с FPU оставались в тени. Вычисления с плавающей точкой выполняются блоком FPU параллельно с работой основной программы, иногда даже быстрее вычислений, производимых блоком IEU. И программисты стали перекладывать основную тяжесть вычислений на блок FPU.
Блок FPU поддерживает следующие типы данных:

Типы данных, обрабатываемых блоком FPU
Тип Обозначение Размер Диапазон значений
Короткое вещественное DD/REAL4 4 байта От +/- 1,18*10-38 до +/-3,4*1038
Длинное вещественное DQ/REAL8 8 байт От +/- 2,23*10-308 до +/-1,79*10308
Расширенное вещественное DT/REAL10 10 байт От +/-3,37*10-4932 до +/-1,18*104932
Целое слово DW/SWORD 2 байта От -32768 до +32767
Короткое целоеDD/SDWORD 4 байта От -231 до +231-1
Длинное целоеDQ/SQWORD 8 байт От -263 до +263-1
Упакованное десятичное DT/TBYTE 10 байт От -999999999999999999 до +999999999999999999
Таблица 11.1

Вещественные форматы IEEE, применяемые в микропроцессорах Intel
Тип РазмерСоответствие вещественному числу в C/C++Формат числа (в битах)
знак порядок мантисса
DD/REAL4 4 байта короткое (float) 1 8 23
DQ/REAL8 8 байт длинное (long, double) 1 11 52
DT/REAL10 10 байт расширенное (long double) 1 15 64
Таблица 11.2
Процессор передает числовые данные в блок FPU, который осуществляет необходимые вычисления и возвращает результат.
Для ассемблирования команд FPU, если модель вашего микропроцессора младше i80486, необходимо добавлять параметр – .8087,.287,.387
Названия всех команд FPU начинаются с буквы F. Чтобы вам было легче запомнить назначение команд FPU, обратите внимание на следующую таблицу:

Расшифровка аббревиатур в командах FPU
Буква в команде ОбозначениеПример
I Операнд – целое число (Integer целое)fild, fist, fiadd, fisub, ficomp
B Операнд – упакованное двоично-десятичное число (packed Binary-coded decimal)fbld,fbst
отсутствие буквы Операнд – действительное числоfld, fst, fadd, fsub
P в конце команды выборка операнда из стека (to pop вытолкнуть)fstp, faddp, fsubp
P в середине командыpartial - частичныйfptan, fprem, fprem1
PP в конце команды выборка из стека двух операндовfcompp
R в конце команды или перед P Обратный (Reverse переставленный) порядок операндовfdivr, fsubr
Таблица 11.3
Специальные численные значения
Знак
Порядок
(78-64 биты)
Мантисса
(63-0 биты)
Название числа
0 000...00000000 000...00000000000 +0
1 000...00000000 000...00000000000 -0
0 111...11111111 000...00000000000 https://www.cyberforum.ru/cgi-bin/latex.cgi?+\infty (+infinity)
1 111...11111111 000...00000000000 https://www.cyberforum.ru/cgi-bin/latex.cgi?-\infty (-infinity)
х 000...00000000 ххх...хххххххххххДенормализованные числа, используются для работы с очень маленькими числами от +/-10-4932 до +/-10-16445
х 111...11111111 10ххх...хххххххххНечисло типа SNAN (Signal Non A Number). Среди х есть единицы. FPU реагирует на появление SNAN возбуждением исключения недействительной операции
х 111...11111111 11ххх...ххххххххх Нечисло типа QNAN (Quiet Non A Number). Среди х есть единицы
1 111...11111111 1100...0000000000 Неопределенность (один из вариантов QNAN)
Таблица 11.4
Несмотря на большой диапазон вещественных значений, представимых в регистрах данных FPU, значения, например, https://www.cyberforum.ru/cgi-bin/latex.cgi?+\infty и https://www.cyberforum.ru/cgi-bin/latex.cgi?-\infty находятся за пределами этого диапазона. Для того, чтобы иметь возможность реагировать на некоторые вычислительные ситуации, которые могут возникнуть в результате математических операций в блоке FPU, предусмотрены специальные комбинации битов, называемые специальными численными значениями. Над специальными численными значениями можно выполнять некоторые операции. Программист может и сам кодировать специальные численные значения директивой DT (х – любое значение бита).
Если в результате вычислений мантисса и порядок равны нулю, то, несмотря на скрытую единицу в целой части числа REAL4/8, все число полагается равным нулю. Любой конечный результат операции FPU, который из-за ограниченности поля порядка не может быть представлен в 23/52/64 разрядах для REAL4/8/10, соответственно вызывает особый случай некорректности представления числа.
Некоторые особенности арифметических операций
с числами с плавающей запятой
Работа с числами с плавающей запятой соответствует работе с дробями (чем собственно они и являются) и при выполнении сложения и вычитания над числами с плавающей запятой эти числа приводятся к общему знаменателю. Пусть: https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1}=m_{1}\times 2^{n}, https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{2}=m_{2}\times 2^{q} Результаты выполнения умножения и деления будут соответственно:
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1}\times x_{2} = (m_{1}\times m_{2})\times 2^{n+q}
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1}/x_{2} = (m_{1} / m_{2})\times 2^{n-q}
При умножении нужно перемножить мантиссы и сложить показатели степени, при делении – разделить мантиссы и вычесть из показателя степени делимого показатель степени делителя, а затем нормализовать число с плавающей запятой.
При выполнении сложения/вычитания возможны два варианта. Если показатели степени равны (https://www.cyberforum.ru/cgi-bin/latex.cgi?n=q), сложение/вычитание реализуются элементарно:
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1} + x_{2} = (m_{1} + m_{2} )\times 2^{q}
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1} - x_{2} = (m_{1} - m_{2} )\times 2^{q}
То есть, просто выносим https://www.cyberforum.ru/cgi-bin/latex.cgi?2^{q} за скобку и складываем/вычитаем мантиссы, а затем нормализуем число. Если показатели степени отличаются (пусть https://www.cyberforum.ru/cgi-bin/latex.cgi?n>q), нужно выровнять значения показателей степени:
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1} + x_{2} = (m_{1} + m_{2}\times 2^{n-q})\times 2^{q}
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1} - x_{2} = (m_{1} - m_{2}\times 2^{n-q})\times 2^{q}
После чего приводим https://www.cyberforum.ru/cgi-bin/latex.cgi?m_{2}\times 2^{n-q} к нормальному (то есть к обычному, без показателя степени) виду, складываем или вычитаем его с/от https://www.cyberforum.ru/cgi-bin/latex.cgi?m_{1}. Результат сложения/вычитания будет мантиссой суммы/разности, а показателем степени суммы/разности будет https://www.cyberforum.ru/cgi-bin/latex.cgi?q.
Теоретически в вашем распоряжении потенциально бесконечное количество разрядов для записи мантиссы и показателя степени, на практике наши ресурсы ограничены – при аппаратной реализации количество разрядов фиксировано, так как регистры имеют конечный и вполне конкретный размер, FPU рассчитано на работу с определённым форматом данных, всё, что в него не помещается, придется так или иначе отбросить. Естественно,
это приводит к потере точности и необходимости правильного округления. А иногда и к переполнениям. Переполнение при выполнении операций плавающей арифметики распознается по слишком большому (большему чем максимально представимый при данной разрядности) положительному значению порядка. При получении результата со слишком большим по модулю отрицательным порядком, возникает проблема исчезновения порядка;
в этом случае в качестве результата обычно берут 0 и продолжают вычисления дальше. Вследствие ограниченного числа разрядов мантиссы при выполнении большей части операций возникают ошибки округления.
Допустим, FPU нашего компьютера работает с десятичными числами (чтобы лучше увидеть результат), может хранить только три десятичных разряда мантиссы и один десятичный разряд показателя степени. Тогда:
https://www.cyberforum.ru/cgi-bin/latex.cgi?1,23\times 10^{4}+3,45\times 10^{-3}=(1,23+0,000000345)\times 10^{4}=1,230000345\times 10^{4}=
=(округляем до трёх значащих разрядов)https://www.cyberforum.ru/cgi-bin/latex.cgi?=1,23\times 10^{4}
https://www.cyberforum.ru/cgi-bin/latex.cgi?1,23\times 10^{4}-3,45\times 10^{-3}=(1,23-0,000000345)\times 10^{4}=1,229999655\times 10^{4}=
=(округляем до трёх значащих разрядов)https://www.cyberforum.ru/cgi-bin/latex.cgi?=1,23\times 10^{4}
Ошибки округления при сложении и вычитании
Возьмём два числа https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{1}{3} и https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{1}{7}, выполним корректное округление до четырех знаков после запятой, а затем вычтем одно число из другого:
https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{1}{3}-\frac{1}{7}\approx 0,3333-0,1429=0,1904
А теперь наоборот – сначала вычтем, а потом переведём в десятичную дробь:
https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{1}{3}-\frac{1}{7}=\frac{7-3}{21}=\frac{4}{21}\approx 0,1905
Результаты получились разные. В данном случае погрешность преобразования из обыкновенной дроби в десятичную дробь с четырьмя знаками после запятой не превышает половины младшего разряда, но числа подобраны так, что при вычитании погрешности складываются, и суммарная погрешность оказывается больше.
Математически-одинаковые числа, полученные двумя разными способами, на практике могут оказаться разными – из-за различий в последовательности выполнения округления.
Складывать большие и маленькие числа нужно осторожно. Например, если нужно с большой точностью сложить много чисел, то начинать стоит с самых маленьких и складывать не всё подряд, а группировать числа так, чтобы всё время суммировать значения приблизительно одного порядка:
https://www.cyberforum.ru/cgi-bin/latex.cgi?((((12 + 0,42) + 0,43) + 0,45) + 0,48) \approx  12
https://www.cyberforum.ru/cgi-bin/latex.cgi?12 + (0,42 + 0,43 + 0,45 + 0,48) = 14
С математической точки зрения, операции сложения и вычитания чисел с плавающей запятой не ассоциативны, то есть
https://www.cyberforum.ru/cgi-bin/latex.cgi?(a + b) + c \neq  a + (b + c)
Вычитание маленького числа из большого работает так же, как и сложение – при определённых условиях, маленькое число можно просто отбросить.
https://www.cyberforum.ru/cgi-bin/latex.cgi?6780 - 3,14 = 6776,86 = (округляем до ближайшего числа с учётом текущей точности https://www.cyberforum.ru/cgi-bin/latex.cgi?- 10) = 6780
Вычитаем большое число из большого.
6781,35 – 6774,22 = 7,13
Получается три знака, даже округлять не надо. Но если округление произвести до вычитания, тогда:
6781,35 – 6774,22 = 6780 – 6770 = 10,0.
Проблема в том, что в результате получается маленькое число с маленькой точностью. Если в исходных числах после округления было три
верных знака, то у результата – только один. Если на это число далее будут что-нибудь умножать-делить, то ошибка будет распространяться и расти дальше.
Ошибки округления при умножении
Умножением в столбик легко проверить – если умножаются два https://www.cyberforum.ru/cgi-bin/latex.cgi?n-разрядных числа, то результат получается https://www.cyberforum.ru/cgi-bin/latex.cgi?2n-разрядным или https://www.cyberforum.ru/cgi-bin/latex.cgi?2n-1. Это верно, если исходные числа – точные (например, целые). Если же число не целое, а получено из какой-то функции (синус, логарифм) или переводом из другой системы счисления, оно никогда не будет точным, в лучшем случае оно получается с точностью до половины младшего разряда.
Перемножим 345 на 47,8 – истинный результат равен 16491,0. Как и ожидалось, получили шесть цифр. Теперь перемножим те же числа с точностью до половины младшего разряда числа: https://www.cyberforum.ru/cgi-bin/latex.cgi?(345\pm 0,5)\times(47,8\pm 0,05) – реальный результат будет находиться где-то между 16449,875 и 16532,175. Из восьми цифр, истинному результату соответствуют только первые две, в третьей цифре возможна ошибка равная ±1. Вывод – если перемножаются числа с точностью до https://www.cyberforum.ru/cgi-bin/latex.cgi?n знаков, тогда точность произведения будет тоже примерно https://www.cyberforum.ru/cgi-bin/latex.cgi?n знаков. Для реального результата имеет смысл оставить только старшие https://www.cyberforum.ru/cgi-bin/latex.cgi?n разрядов, а младшие разряды отбросить.
Именно так и обрабатывают произведения чисел с плавающей запятой.
Старшие https://www.cyberforum.ru/cgi-bin/latex.cgi?n разрядов укладываются в https://www.cyberforum.ru/cgi-bin/latex.cgi?n-разрядную мантиссу, младшие – округляются:
https://www.cyberforum.ru/cgi-bin/latex.cgi?345\times 47,8=3,45\times 10^{2}\times 4,78\times 10^{1}=1,6491\times 10^{4}=(округляем до трех цифр)=https://www.cyberforum.ru/cgi-bin/latex.cgi?1,65\times 10^{4}
Исключение делается при умножении числа на число, которое представляет собой степень двойки, мантисса произведения будет равна мантиссе первого числа – меняется только степень числа, округление не производят.
Программная модель FPU
Блок FPU предоставляет для программирования восемь регистров для хранения данных (R0-R7) и пять вспомогательных регистров: регистр SWR (State Word Register регистр состояния), регистр CWR (Control Word Register регистр управления), регистр TW (Tag Word регистр атрибутов) и регистры FIP (FPU Instruction Pointer) и FDP (FPU Data Pointer).
Регистры данных R0-R7
Регистры данных не адресуются по именам, а рассматриваются в качестве стека, вершина которого называется ST(0). Если в какой-то момент вершина стека (поле TOP регистра SWR) указывает на регистр R5 и его считают ST(0), то после записи числа в R5, вершина стека будет указывать на регистр R4 и уже он будет ST(0), а R5 – ST(1) и так далее.
Регистр тэгов TW
Регистр тэгов хранит состояние содержимого каждого регистра данных (на каждый регистр данных отведено по 2 бита). Содержимое регистра данных может быть
Tag Field Содержимое
00 Число в формате с плавающей запятой (valid)
01 Нулевое значение
10 Специальное значение (SNAN, QNAN, бесконечность, денормализованное или не поддерживаемое число)
11 Пусто (empty)

Регистры FIP и FDP
Регистры FIP (FPU Instruction Pointer) и FDP (FPU Data Pointer) содержат адрес последней выполненной команды (за исключением команд FINT, FCLEX, FLDCW, FSTSW, FSTSWAX, FSTENV, FLDENV, FSAVE, FRSTORE и FWAIT) и адрес ее операнда соответственно, и используются в обработчиках исключений для анализа вызвавшей его команды.
Регистр состояний RSW
Регистр состояния фиксирует различные ошибки, хранит код условий для некоторых команд, определяет регистр – вершину стека и показывает состояние занятости блока FPU:
Бит Название Назначение
15 FPU busy Занятость FPU. Этот флаг существует для совместимости с i8087, и его значение всегда совпадает с ES.
14,10–8Condition Code (С3, С2, С1, С0)Условные флаги. Употребляются так же, как и биты состояния в регистре EFLAGS, значения С0–С3 отражают результат выполнения предыдущей команды блока FPU и используются для условных переходов. Значения С0–С3 копируют в регистр EFLAGS: флаг С0 переходит в CF, https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2}\rightarrow PF, https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{3}\rightarrow ZF, флаг https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2} теряется.
13–11 Тop of Stack PointerЧисло от 0 до 7, показывающее, какой из регистров данных R0–R7 в настоящий момент является вершиной стека.
7 Error Summary StatusОбщий флаг ошибки. Если ES=1, произошло хотя бы одно немаскированное исключение.
6 Stack FaultОшибка стека. Если С1=1, произошло переполнение (команда пыталась писать в непустую позицию в стеке), если С1=0, произошло антипереполнение (команда пыталась считать число из пустой позиции в стеке).
5 precision Флаг неточного результата – результат не может быть представлен точно.
4 Underflow Флаг антипереполнения – результат слишком маленький.
3 overflow Флаг переполнения – результат слишком большой.
2 Zero Divide Флаг деления на ноль – выполнено деление на ноль.
1 Denormalized OperandФлаг денормализованного операнда – выполнена операция над денормализованным числом.
0 Invalid OperationФлаг недопустимой операции – произошла ошибка стека (SF=1) или выполнена недопустимая операция.
Биты 0–5 отражают различные ошибочные ситуации, которые могут возникать при выполнении команд FPU. Они рассмотрены в описании управляющих регистров.
Регистр управления RCW
Регистр управления содержит слово управления блока FPU:
Биты Название Назначение
15–13зарезервированы
12 Infinity Controlуправление бесконечностью (поддерживается для совместимости с i8087 и i80287 – вне зависимости от значения этого бита https://www.cyberforum.ru/cgi-bin/latex.cgi?+\infty больше чем https://www.cyberforum.ru/cgi-bin/latex.cgi?-\infty)
11–10 Rounding Control управление округлением
9–8 precision Control управление точностью
7–6зарезервированы
5 precision Mask маска неточного результата
4 Underflow Mask маска антипереполнения
3 overflow Mask маска переполнения
2 Zero divide Mask маска деления на ноль
1 Denormalized Operand Mask маска денормализованного операнда
0 Invalid Operation Mask маска недействительной операции
Биты 0–5 регистра CRW маскируют соответствующие исключения – если маскирующий бит установлен, исключения не происходит, а результат вызвавшей его команды определяется правилами для каждого исключения специально.

Рисунок 11.2.1. Регистры блока FPU
С появлением Pentium MMX произошло расширение системы команд за счет включения 57 новых инструкций, разработанных для более эффективной работы с мультимедийными данными. Параллельное исполнение повторяющихся последовательностей команд целочисленной арифметики, часто встречающихся при работе мультимедиа-приложений, происходит в 64-битных регистрах MM0-MM7. Физически никаких новых регистров с введением технологии MMX не появилось, регистры MM0-MM7 – это мантиссы восьми регистров блока FPU от R0 до R7. При записи числа в регистр MMX оно оказывается в битах 63-0 соответствующего регистра FPU. А порядок (биты 78-64) и ее знаковый бит (бит 79) заполняются единицами. Запись числа в регистр FPU также приводит к изменению содержания соответствующего регистра MMX.
Любая команда MMX, кроме EMMS, приводит к тому, что поле TOP регистра SR и весь регистр TW в FPU обнуляется. Команда EMMS заполняет регистр TW единицами. Нельзя одновременно пользоваться командами для работы с числами с плавающей запятой и командами MMX, если возникла такая необходимость – применяют команды FSAVE/FRSTOR при переходе от FPU к MMX. Для доступа к регистрам данных (R0-R7) FPU можно использовать команды для доступа к регистрам MM0-MM7.
Практическая работа с блоком FPU
«Сколько не говори халва – во рту слаще не станет»
Восточная мудрость
Напишем первую программу с использованием команд FPU
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.686P
.model flat
include windows.inc
includelib user32.lib
extern _imp__MessageBoxA@16:dword
extern _imp__wsprintfA:dword
.code
start: finit;инициализируем FPU
fild X;выбрали число из памяти
fsqrt;получили квадратный корень
fist result
push result
push offset format
push offset buffer
call _imp__wsprintfA;преобразуем для вывода на экран
add esp,4*3;балансируем стек после вызова wsprintfA
push 0
push offset caption
push offset buffer
push 0
call _imp__MessageBoxA@16;выводим на экран
ret
format db 'корень=%08u',0
buffer db 50 dup (0)
caption db 'квадратный корень',0;заголовок
X dd 25;число из которого берем квадратный корень
result dd 0;место под результат
end start
Запускаем программу и любуемся на результат (рис. 11.2.2)
Команда fild X (Integer LOAD) – загружает целое число из ячейки памяти X в ST(0). При загрузке числа блок FPU преобразует входное значение из формата знакового целого (16-, 32-, 64-битного) в формат с плавающей точкой. Следующая команда fsqrt (SQUARE ROOT) – извлекает квадратный корень из числа в ST(0). Команда fist result (Integer STORE) – копирует содержимое регистра ST(0) в ячейку памяти result, при этом выполняется обратное преобразование из внутреннего формата FPU в формат знакового целого с округлением результата. Текущий режим округления – к ближайшему значению – установлен в результате выполнения команды finit (Floating-point unit INITIALIZE).

рис. 11.2.2
Обратная польская нотация
Форма представления изобретена польским математиком-логиком Яном Лукасевичем (Łukasiewicz, 1878–1956). В ней каждый оператор записывается вслед за относящимся к нему операндами. Таким образом, например, https://www.cyberforum.ru/cgi-bin/latex.cgi?a+b представляется как https://www.cyberforum.ru/cgi-bin/latex.cgi?ab+, https://www.cyberforum.ru/cgi-bin/latex.cgi?a+b\times c записывается как https://www.cyberforum.ru/cgi-bin/latex.cgi?abc\times +. Если каждому оператору соответствует определенное число операндов, например, точно два, то скобки при такой записи не нужны, поскольку порядок вычислений всегда определяется однозначно; поэтому данная запись может быть названа бесскобочной. Важность RPN (reverse polish notation – обратная польская нотация) определяется тем, что выражения в такой форме легко вычисляются с использованием стека. Таким образом, перевод выражения в RPN и последующее вычисление с использованием стековой памяти определяют простой, но весьма эффективный путь обработки арифметических выражений.
Набор команд для работы с плавающей запятой в процессорах Intel достаточно разнообразен, чтобы реализовывать весьма сложные алгоритмы, и прост в использовании. Единственное, что может представлять определенную сложность, – почти все команды FPU по умолчанию работают с его регистрами данных как со стеком, выполняя операцию над числами в ST(0) и ST(1) и помещая результат в ST(0), так что естественной формой записи математических выражений для FPU оказывается RPN. Для FPU сначала преобразовывают обычные математические выражения в выражения RPN, а потом на основе RPN пишут программу.
Преобразование выражение, записанного в RPN, в процедуру вычисления арксинуса.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
; arcsin(x) вычисляем арксинус числа x -1 [LATEX]\leq[/LATEX] х [LATEX]\leq[/LATEX] +1)
; по формуле arcsin(x) = arctg(x/sqrt(1-x2))
; после преобразования в RPN получаем x x * 1 - sqrt atan
; результат возвращаем в переменную result
.686P
.model flat
include windows.inc
includelib user32.lib
extern _imp__MessageBoxA@16:dword
extern _imp__wsprintfA:dword
.code ;содержимое стека FPU
start: finit ; st(0) st(1) st(2)
fld X ; sin(x) -- --
fld st(0) ; sin(x) sin(x) --
fmul st(0),st(0) ; sin2(x) sin(x) --
fld1 ; 1 sin2(x) sin(x)
fsubr ;1-sin2(x)=cos2(x) sin(x) --
fsqrt ; cos(x) sin(x) --
fpatan ;arctg(st(1)/st(0))
fmul coeff;переводим значение угла из радианов в градусы
fist result
push result
push offset format
push offset buffer
call _imp__wsprintfA;преобразуем для вывода на экран
add esp,4*3;балансируем стек после вызова wsprintfA
push 0
push offset caption
push offset buffer
push 0
call _imp__MessageBoxA@16;выводим результат на экран
ret
format db 'arcsin(x)=%lu',0
buffer db 50 dup (0)
caption db 'arcsin(x)',0
X dd 0.5
coeff dd 57.32;=180/p коэффициент для перевода радианов в градусы
result dd 0.0
end start
Система команд блока FPU
Команды блока FPU по выполняемым им функциям делят на шесть групп: передача данных, арифметические, сравнения, трансцендентальные, оперирующие константами и команды управления.
Кодировка всех команд блока FPU начинается с 11011xxx (с 0D8h по 0DFh) (ESC1-ESC7 «ESC-коды»).
Команды передачи данных
Команды FLD

(загрузка числа в FPU = ”Floating point LOAD”)
Синтаксис команды:
FLD <SRC>
Алгоритм работы: загрузки числа в регистр данных блока FPU.
Возможные варианты команды:
fild mem
fbld mem
fld mem
fld st(i)
Псевдокод команды
:
IF SRC =ST(i)
THEN temphttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(i)
ENDIF
TOPhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowTOP-1
IF SRC is memory-operand
THEN ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowConvertToDoubleExtendedPrecisionFP(SRC)
ELSE ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow temp
END IF
Применение:
  • FILD SRC – загрузка в регистр FPU ST(0) целого числа из ячейки памяти SRC. Область памяти SRC должна быть 16-, 32-, 64-битной;
  • FBLD SRC – загрузка в ST(0) десятичного упакованного числа из 80-битной области памяти SRC;
  • FLD SRC – загрузка в ST(0) действительного числа из памяти. Область памяти SRC должна быть 32-, 64-, 80-битной;
  • FLD ST(i) – загрузка в регистр ST(0) содержимого регистра ST(i).
Все команды помещаются число в ST(0), увеличивая указатель стека на 1 (ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\rightarrowST(1)) и уменьшая значение поля TOP в регистре TW на 1.
Хотя используется одна и та же инструкция FLD SRC, но по типу имени операнда SRC ассемблер подбирает одну из четырех команд с разными опкодами (в кодах ясно угадывается адрес ячейки памяти 400174h, записанный в обратном порядке 74014000, и индекс регистра FPU), то же можно сказать и о команде FILD SRC.
Команда hex Опкод
FLD dword ptr [400174h] D90574014000 D9/0
FLD qword ptr [400174h] DD0574014000 DD/0
FLD tbyte ptr [400174h] DB2D74014000 DB/5
FLD ST(i) D9Ci D9C0+i
FILD word ptr [400174h] DF0574014000 DF/0
FILD dword ptr [400174h] DB0574014000 DB/0
FILD qword ptr [400174h] DF2D74014000 DF/5
FBLD tbyte ptr [400174h] DF2574014000 DF/4
Команда FLD ST(0) дублирует вершину стека. После нее регистры ST(0) и ST(1) имеют одинаковое значение.
Команда hex Опкод Код операции ESC  Mod  R/M
FLD m32fp D905 D9/0 1101.1 001 00 000 101
FLD m64fp DD05 DD/0 1101.1 101 00 000 101
FLD m80fp DB2D DB/5 1101.1 011 00 101 101
FLD ST(i) D9Ci D9C0+i 1101.1 001 11 000 i
FILD m16int DF05 DF/0 1101.1 111 00 000 101
FILD m32int DB05 DB/0 1101.1 011 00 000 101
FILD m64int DF2D DF/5 1101.1 111 00 101 101
FBLD m80bcd DF25 DF/4 1101.1 111 00 100 101
Mod=11 режим регистровой адресации. R/M=ST(i)
Mod=00 R/M=101 режим прямой адресации, в следующем байте 32-битное смещение ячейки памяти
Команда FLD ST(3) помещает содержимое ST(3) в ST(0). Число, которое имело адрес ST(3), имеет теперь адрес ST(4). Но если специально не указывать номер регистра данных FPU, то по команде FLD загружаемое в FPU число попадает в ST(0), при этом числа, уже хранящиеся в других регистрах, смещаются на шаг от вершины стека. Стек FPU может хранить только 8 чисел – столько, сколько в нем регистров. Попытка загрузить в стек девятое число приведет к потере числа, далее всего отстоящего от вершины. Но и ST(0) при этом не воспримет то, что в него загружается, и будет содержать некое значение, которое с точки зрения FPU не может быть числом. Загрузим FPU числами 1, 2, 3, …, 9. Первым в FPU оказалось число 1.0. Оно заняло вершину стека, то есть регистр ST(0). Далее в ST(0) было загружено число 2.0, а число 1.0 спустилось ниже – в регистр ST(1). Затем в ST(0) побывали числа 3.0, 4.0, 5.0, 6.0, 7.0, 8.0. Число 1.0, попавшее в ST(0) первым, спускалось все ниже и оказалось, наконец, в регистре ST(7), когда в ST(0) было число 8.0. Но, при попытке поместить в ST(0) девятое число, случилась авария: число 1.0, загруженное первым, покинуло стек, а на его вершине оказалось неверное значение, которое в регистре тэгов помечено атрибутом NAN (Non A Number нечисло). Кроме «нечисел» в стеке могут быть нормальные числа, помеченные атрибутом valid (правильный). Таковы все числа кроме первого. У регистров ST(0)-ST(7) может быть еще один атрибут empty (пустой). Так блок FPU помечает регистр, в который можно загрузить число. Если регистр занят, то его нужно перед использованием освободить. Делается это командой ffree (FREE Floating-point register). Чтобы, например, освободить третий регистр, нужна команда ffree ST(3). Есть еще одна команда finit, которая разом освобождает сразу все регистры и чаще всего используется для приведения стека данных в «исходное» состояние.
Команды FST
( извлечение числа из FPU в память =”STORE Floating point value”)
Синтаксис команды:
FST <DEST>
Алгоритм работы: сохранение числа из регистра данных блока FPU в ячейку памяти.
Возможные варианты команды:
fist mem
fistp mem
fistpp mem
fbstp mem
fstp mem
Псевдокод команды
:
IF Команда = FSTP
THEN DESThttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(0)
ELSE IF Команда = FBSTP
THEN DESThttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowПреобразовать_в_BCD(ST(0))
ELSE IF Команда = FISTP или FIST
THEN DESThttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowПреобразовать_в_целое(ST(0))
ENDIF;
IF Команда = FISTP или FSTP или FBSTP
THEN Вытолкнуть_содержимое_регистра_из_стека
ENDIF;
Применение: команда FST извлекает число из вершины стека и записывает его в ячейку памяти DEST. Область памяти DEST должна быть 32-, 64-, 80-битной. Команда FSTP выполняет операцию записи данных из FPU в память и извлекает число из стека.
Команда hex Опкод Код операции ESC Mod  R/M
FST m32fp D915 D9/2 1101.1 001 00 010 101
FST m64fp DD15 DD/2 1101.1 101 00 010 101
FST ST(i) DDDi DDD0+i 1101.1 101 11 010 i
FIST m16int DF15 DF/2 1101.1 111 00 010 101
FIST m32int DB15 DB/2 1101.1 011 00 010 101
FSTP m32fp D91D D9/3 1101.1 001 00 011 101
FSTP m64fp DD1D DD/3 1101.1 101 00 011 101
FSTP m80fp DB3D DB/7 1101.1 011 00 111 101
FSTP ST(i) DDDF DDD80+i 1101.1 101 11 011 i
FISTP m16int DF1D DF/3 1101.1 111 00 011 101
FISTP m32int DB1D DB/3 1101.1 011 00 011 101
FISTP m64int DF3D DF/7 1101.1 111 00 111 101
FBSTP m80bcd DF35 DF/6 1101.1 111 00 110 101
Команда FXCH
(обмен значениями в регистрах FPU = ”EXCHGE register contents”)
Синтаксис команды:
FXCH <SRC>
Семантика команды: команда обмена значения в регистре стека ST(0) со значением регистра ST(i)
Возможные варианты команды:
fxch st(i)
fxch
Псевдокод команды:
IF количество_операндов=1
THEN
temphttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(0)
ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowSRC
SRChttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowtemp
ELSE
temphttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(0)
ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(1)
ST(1)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowtemp
ENDIF
команда опкод Код операции ESC  Mod  R/M
FXCH ST(i) D9C8+i 1101.1 001 11 001 i
FXCH D9C9 1101.1 001 11 001 001
Команда FXCH меняет местами содержимое ST(0) с содержимым ST(i). Если операнд не указан, то обмениваются ST(0) и ST(1).
Арифметические команды
Команды FADD

(сложение значений в регистрах FPU = ” Floating point ADDITION”)
Синтаксис команды:
FADD <DEST>,<SRC>
Семантика команды: команда сложения вещественных чисел.
Возможные варианты команды:
fadd st(0),st(i)
fadd st(i),st(0)
fadd mem
faddp st(i),st(0)
fiaddp mem
Псевдокод команды
:
IF Команда=FIADD
THEN DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow DEST + ConvertToDoubleExtendedPrecisionFP(SRC)
ELSE; операнд в SRC представлен в виде числа с плавающей запятой
DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow DEST + SRC
ENDIF
IF Команда=FADDP
THEN Вытолкнуть_содержимое_регистра_из_стека
ENDIF

9-8 биты регистра управления RCW – биты PC (Рrecision Control) определяют точность результатов команд FADD, FSUB, FSUBR, FMUL, FDIV, FDIVR и FSQRT .
PC Точность результатов
00 одинарная точность (32-битные числа)
01 зарезервировано
10 двойная точность (64-битные числа)
11 расширенная точность (80-битные числа)
Кодировка FADD
Пример Опкод Действие
FADDP DEC1 ST(1) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) + ST(1), извлечь из стека
FADD ST(0),ST(i) D8C0+i ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) + ST(i)
FADD ST(i),ST(0) DCC0+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) + ST(i)
FADDP ST(i),ST(0) DEC0+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST0 + ST(i), извлечь из стека
FADD m32fp D8/0 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) + [m32fp]
FADD m64fp DC/0 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) + [m64fp]
FIADD m32int DA/0 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) + [m32int]
FIADD m16int DE/0 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) + [m16int]
Команды FSUB
(вычитание значений в регистрах FPU =”Floating point SUBTRACT”)
Синтаксис команды:
FSUB <DEST>,<SRC>
Семантика команды: команда вычитания вещественных чисел.
Возможные варианты команды:
fsub
fsub st(0),st(i)
fsub st(i),st(0)
fsub mem
fisub st(i),st(0)
fsubr
fsubr st(0),st(i)
fsubr st(i),st(0)
fsubr mem
fsubrp st(i),st(0)
fisubrp mem
Псевдокод команды
:
IF Команда=FISUB
THEN DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow DEST - ConvertToDoubleExtendedPrecisionFP(SRC)
ELSE IF Команда=FSUB
; операнд в SRC представлен в виде числа с плавающей запятой
DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow DEST - SRC
ELSE IF Команда=FISUBR
DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowConvertToDoubleExtendedPrecisionFP(SRC) - DEST
ELSE IF Команда=FSUBR
; операнд в SRC представлен в виде числа с плавающей запятой
DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow SRC - DEST
ENDIF
IF Команда=FSUBP или FSUBRP
THEN Вытолкнуть_содержимое_регистра_из_стека
ENDIF
Кодировка FSUB
Операция Опкод Действие
FSUB m32fp D8/4 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) - [m32fp]
FSUB m64fp DC/4 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) -[m64fp]
FSUB ST(0),ST(i) D8E0+i ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) -ST(i)
FSUB ST(i),ST(0) DCE8+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(i) -ST(0)
FSUBP ST(i),ST(0) DEE8+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(i) -ST(0), извлечь из стека
FSUBP DEE9 ST(1) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) -ST(1), извлечь из стека
FISUB m32int DA/4 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) - [m32int]
FISUB m16int DE/4 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) -[m16int]
FSUBR m32fp D8/5 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m32fp] - ST(0)
FSUBR m64fp DC/5 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m64fp] -ST(0)
FSUBR ST(0),ST(i) D8E0+i ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(i) -ST(0)
FSUBR ST(i),ST(0) DCE0+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) -ST(i)
FSUBRP ST(i),ST(0) DEE0+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) -ST(i), извлечь из стека
FSUBRP DEE1 ST(1) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(1) -ST(0), извлечь из стека
FISUBR m32int DA/5 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m32int]-ST(0)
FISUBR m16int DE/5 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m16int]-ST(0)
команда FSUB mem это https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0) \leftarrow ST(0) - [mem] если ST(0)=0 тогда ST(0) = -[mem] получаем эквивалент команды, которой нет FCHS mem
Результаты действия fsubp, fsubrp и fsub st(0),st(1) эквивалентны.
Команды FMUL
(умножение значений в регистрах FPU = ”Floating point MULTIPLY”)
Синтаксис команды:
FMUL <DEST>,<SRC>
Семантика команды: команда умножения вещественных чисел
Возможные варианты команды:
fmul
fmul st(i),st(0)
fmul st(0),st(i)
fmul mem
fmulp
fimul mem
Псевдокод команды
:
IF Команда=FIMUL
THEN DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\times ConvertToDoubleExtendedPrecisionFP(SRC)
ELSE; операнд в SRC представлен в виде числа с плавающей запятой
DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\times SRC
ENDIF
IF Команда=FMULP
THEN Вытолкнуть_содержимое_регистра_из_стека
ENDIF
Кодировка FMUL
Операция Опкод Действие
FMUL m32fp D8/1 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow [m32fp]\times ST(0)
FMUL m64fp DC/1 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow [m64fp] \times ST(0)
FMUL ST(0),ST(i) D8CB+i https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow ST(i) \times ST(0)
FMUL ST(i),ST(0) DCCB+i https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(i)\leftarrow ST(i) \times ST(0)
FMULP ST(i),ST(0) DECB+i https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(i)\leftarrow ST(i) \times ST(0), извлечь из стека
FMULP DEC9 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(1)\leftarrow ST(1) \times ST(0), извлечь из стека
FIMUL m32int DA/1 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow [m32int] \times ST(0)
FIMUL m16int DE/1 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow [m16int] \times ST(0)
Операция деления в FPU происходит дольше, чем операция умножения, поэтому старайтесь заменять деление на константу на умножение на константу в степени –1.
Варианты возведения числа X в квадрат https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow X^{2}
fld x fld x fld x
fld st(0) fmul x fmul st(0),st(0)
fmul  
Команды FDIV
(деление значений в регистрах FPU = ”Floating point DIVIDE”)
Синтаксис команды:
FDIV <DEST>,<SRC>
Семантика команды: команда деления вещественных чисел.
Возможные варианты команды:
fdiv mem
fdiv st(0),st(i)
fdiv st(i),st(0)
fdivp st(i),st(0)
fdivp
fidiv mem
Псевдокод команды
:
IF (Команда=FIDIV или FDIV) и SRC=0
THEN #Z
ELSE IF (Команда=FIDIVR или FDIVR) и DEST=0
THEN #Z
ELSE IF Команда=FIDIV
THEN DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ConvertToDoubleExtendedPrecisionFP(SRC)/DEST
ELSE IF Команда=FDIV
; операнд в DEST представлен в виде числа с плавающей запятой
DEST https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow SRC/ DEST
ENDIF
IF Команда=FDIVP или FDIVRP
THEN Вытолкнуть_содержимое_регистра_из_стека
ENDIF
Кодировка FDIV
Операция Опкод Действие
FDIV m32fp D8/6 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) / [m32fp]
FDIV m64fp DC/6 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) /[m64fp]
FDIV ST(0),ST(i) D8F0+i ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) /ST(i)
FDIV ST(i),ST(0) DCF8+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(i) /ST(0)
FDIVP ST(i),ST(0) DEF8+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(i) /ST(0), извлечь из стека
FDIVP DEF9 ST(1) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(1) /ST(0), извлечь из стека
FIDIV m32int DA/6 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) / [m32int]
FIDIV m16int DE/6 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) /[m16int]
FDIVR m32fp D8/7 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m32fp] / ST(0)
FDIVR m64fp DC/7 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m64fp] /ST(0)
FDIVR ST(0),ST(i) D8F8+i ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(i) /ST(0)
FDIVR ST(i),ST(0) DCF0+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) /ST(i)
FDIVRP ST(i),ST(0) DEF0+i ST(i) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) /ST(i), извлечь из стека
FDIVRP DEF1 ST(1) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow ST(0) /ST(1), извлечь из стека
FIDIVR m32int DA/7 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m32int]/ST(0)
FIDIVR m16int DE/7 ST(0) https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow [m16int]/ST(0)
Команда FPREM
(вычисления частичного остатка = ”Partial REMAINDER”)
Синтаксис команды:
FPREM
Семантика команды: команда вычисления частичного остатка.
Remainderhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(0) -(Qhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\timesST(1))
Псевдокод команды:
Dhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowexponent(ST(0))-exponent(ST(1))
IF D<64
THEN
Qhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowInteger(TruncateTowardZero(ST(0)/ST(1)))
ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(0) -(ST(1)https://www.cyberforum.ru/cgi-bin/latex.cgi?\timesQ)
C2https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
C0,C3,C1LeastSignificantBits(Q); Q2Q1Q0
ELSE
C2https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1
Nhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowчисло между 32 и 63
QQhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowInteger(TruncateTowardZero(ST(0)/ST(1))/2(D-N))
ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(0) -(ST(1)https://www.cyberforum.ru/cgi-bin/latex.cgi?\timesQQhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\times2(D-N))
ENDIF
Эта команда за один раз уменьшает содержимое вершины стека максимум на 264. Команда выполняет нахождение истинного остатка от деления ST(0) на ST(1) и требует очень много времени для уменьшения большого числа по очень маленькому основанию. Если функция не завершена, команда FPREM устанавливает флаг C2 равным 1, а когда завершает вычисление остатка, то устанавливает другие три флага C3, C1 и C0 равными трем младшим битам частного. Когда команда FPREM используется в простых тригонометрических функциях для ограничения величины угла, это оказывается необходимым для определения октанта первоначального угла.
Assembler
1
2
3
4
5
;контроль выполнения частичного остатка (c2=pf=1)
a1: fprem1
     fstsw ax
     sahf
     jp a1
Команда FPREM1
Синтаксис команды:
FPREM1
Семантика команды: команда вычисления частичного остатка.
https://www.cyberforum.ru/cgi-bin/latex.cgi?Remainder\leftarrow ST(0) -(Q\times ST(1))
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?D\leftarrow exponent(ST(0))-exponent(ST(1))
IF D<64
THEN
Qhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowInteger(RoundTowardNearestInteger(ST(0)/ST(1)))
ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowST(0) -(ST(1)https://www.cyberforum.ru/cgi-bin/latex.cgi?\timesQ)
C2https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
C0,C3,C1LeastSignificantBits(Q); Q2Q1Q0
ELSE
https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2}\leftarrow 1
https://www.cyberforum.ru/cgi-bin/latex.cgi?N \leftarrowчисло между 32 и 63
https://www.cyberforum.ru/cgi-bin/latex.cgi?QQ\leftarrow Integer(TruncateTowardZero(ST(0)/ST(1))/2^{D-N})
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow ST(0)-(ST(1) \times QQ \times 2^{D-N})
ENDIF
Также как и команда FPREM, команда FPREM1 выполняет деление ST(0) на ST(1) и помещает остаток от деления в ST(0). Деление осуществляется при помощи последовательных вычитаний ST(1) из ST(0), но за один раз выполняется не более 64 таких вычитаний.
Команда FRNDINT
(округления вещественного числа до целого =
Floating point ROUND to INTEGER”)
Синтаксис команды:
FRNDINT
Семантика команды: команда округления до целого.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow RoundToIntegerValue(ST(0))
Эта команда округляет текущее содержимое вершины стека до целого числа. Биты RC (Rounding Control) в регистре управления (RCW) определяют способ округления результатов команд блока FPU до заданной точности.
RCСпособ округления
00 к ближайшему числу near
01 к https://www.cyberforum.ru/cgi-bin/latex.cgi?-\infty down
10 к https://www.cyberforum.ru/cgi-bin/latex.cgi?+\infty up
11 к нулю chop/zero
Assembler
1
2
3
4
5
6
7
8
;пример управления округлением
fstcw ax
and eax,1111xx1111111111b;11-10 bits rc
or eax,xx0000000000b
push eax
fldcw word ptr [esp]
pop eax
frndint
Команда FSQRT
(извлечения квадратного корня = ”Floating point SQUARE ROOT”)
Синтаксис команды:
FSQRT
Алгоритм работы: извлечения квадратного корня.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0) \leftarrow \sqrt{ST(0)}
ST(0) не должно быть отрицательно.
Пример: найдем корни квадратного уравнения, заданного формулой:
https://www.cyberforum.ru/cgi-bin/latex.cgi?a\cdot x^{2} + b\cdot x + c= 0
Из школьного курса математики известно, что решением этого уравнения является https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1,2}=\frac{- b\pm \sqrt{b^{2}-4\cdot a\cdot c}}{2\cdot a}.
Программа для решения этого уравнения:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.data
A DW ? ;место под коэффициенты
B DW ?
C DW ?
STATUS DW ?
FOUR DW 4.0 ;нам понадобятся две вещественные константы
TWO DW 2.0 ;FOUR=4,0 и TWO=2,0
ROOT1 DW ? ;место под 1-й корень уравнения
ROOT2 DW ?
.code ;место под 2-й корень уравнения
FINIT ;инициализируем блок FPU
FILD B ;загрузить число в регистр стека ST(0)<-B
FMUL ST(0) ;перемножить числа ST(0)<-B*B
FILD A ;загрузить число в регистр стека, ST(0)<-A
FMUL FOUR ;умножить число в ST(0) на 4.0, ST(0)<-4*A
FIMUL C ;умножить число в ST(0) на C, ST(0)<-4*A*C
FSUBRP ST(1),ST(0) ;вычитаем обратные целые числа
FTST ;проверяем дискриминант на отрицательность
FSTSW STATUS;записываем в память управляющий регистр FPU
FWAIT; и переводим FPU в режим ожидания
MOV AH,BYTE PTR STATUS+1;Читаем в AH
SAHF; помещаем содержимое регистра AH в регистр флагов
JB IMAGINARY;если корни мнимые переходим
FSQRT ;извлекаем квадратный корень в ST(0)
FLD ST(0) ;загрузить число из ST(0) в ST(1),ST(1)<-ST(0)
FCHS ;изменяем знак, ST(0)=-SQRT(D)
FIADD B;складываем целые числа ST(0)=B-SQRT(D)
FCHS ;изменяем знак ST(0)= -B+SQRT(D)
FXCH ST(1);обмениваемся данными между ST(0) и ST(1)
FIADD B;складываем целые числа ST(0)=B+SQRT(D)
FCHS ;изменяем знак, ST(0)= -B-SQRT(D)
FIDIV A;делим на целое число ST(0)= -(B+SQRT(D))/A
FDIV TWO;еще раз делим на 2, ST(0)=-(B+SQRT(D))/2A
FST ROOT1;сохраняем в памяти 1-ый результат из ST(0)
FIDIV A;делим на целое число ST(0)=(-B+SQRT(D))/A
FDIV TWO ;делим на 2 ST(0)=(-B+SQRT(D))/2A
FST ROOT2 ;сохраняем в памяти 2-ой результат
Возможная проблема с потерей точности
Еще раз вернемся к нашей задаче. Решением квадратного уравнения является
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1,2}=\frac{- b\pm \sqrt{b^{2}-4ac}}{2\cdot a}
Пусть https://www.cyberforum.ru/cgi-bin/latex.cgi?b много больше https://www.cyberforum.ru/cgi-bin/latex.cgi?4ac, тогда https://www.cyberforum.ru/cgi-bin/latex.cgi?\sqrt{b^{2} - 4ac} приблизительно равно https://www.cyberforum.ru/cgi-bin/latex.cgi?b. Таким образом, можно получить, что https://www.cyberforum.ru/cgi-bin/latex.cgi?-b+b = 0, значит https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1} = 0, что не является решением задачи. Преобразуем выражение для https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1}:
https://www.cyberforum.ru/cgi-bin/latex.cgi?x_{1}=\frac{-b+\sqrt{D}}{2a}=\frac{-b+\sqrt{D}}{2a}\frac{b+\sqrt{D}}{b+\sqrt{D}}=\frac{D-b^{2}}{2a(b+\sqrt{D})}=\frac{b^{2}-4ac-b^{2}}{2a(b+\sqrt{D})}=-\frac{2c}{b+\sqrt{D}}
и при b, намного большем https://www.cyberforum.ru/cgi-bin/latex.cgi?4ac получаем, что https://www.cyberforum.ru/cgi-bin/latex.cgi?x_1 стремится к https://www.cyberforum.ru/cgi-bin/latex.cgi?-\frac{c}{b}.
Команды масштабирования
(Возведение числа 2 в произвольную степень)
Возведение числа 2 в целую степень. Команда FSCALE
(Масштабирование числа=”Floating point SCALE ST(0) by ST(1)”)
Синтаксис команды:
FSCALE
Семантика команды: команда для возведения 2 в степень, равную целому числу, находящемуся в ST(1) и умножение на содержимое ST(0). Результат в ST(0).
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow ST(0)\times2^{ST(1)}
Возведение числа 2 в дробную степень. Команда F2XM1
(вычисление 2X-1=”Floating point compute 2X-1”)
Синтаксис команды:
F2XM1
Семантика команды: команда вычисления 2 в степени X минус 1.
Псевдокод команды:
ST(0)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow (2^{ST(1)}-1)
Эта функция выполняет возведение в степень; она возводит число 2 в степень, указанную в ST(0). Исходное число должно находиться в диапазоне 0 ≤ ST(0) ≤0,5 и, чтобы возвести в степень большую 0,5, эту команду нужно использовать вместе с командой FSCALE. С помощью команд FLD, загружающих специальные константы, программа может возвести в степень и числа отличные от 2, для этого можно воспользоваться формулами:
https://www.cyberforum.ru/cgi-bin/latex.cgi?2^{x} = (2^{x}-1)+1 = F2XM1(x)+1
https://www.cyberforum.ru/cgi-bin/latex.cgi?e^{X}=2^{X\times log_{2}e}= 1+F2XM1(x\times log_{2}(e)) = 1+ F2XM1(x\times FLDL2E)
https://www.cyberforum.ru/cgi-bin/latex.cgi?10^{X}=2^{X\times log_{2}10}= 1+F2XM1(x\times log_{2}(10)) = 1+ F2XM1(x\times FLDL2T)
https://www.cyberforum.ru/cgi-bin/latex.cgi?X^{Y}=2^{Y\times log_{2}X}= 1+F2XM1(y\times log_{2}(x)) = 1+ F2XM1(FYL2X(y,x))
Команда FXTRACT
(выделения порядка и значащей части =
”EXTRACT exponent and significand”)
Синтаксис команды:
FXTRACT
Семантика команды: выделения порядка и значащей части вещественного числа.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?temp\leftarrow дробная_часть(ST(0))
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrowпоказательная_степень_числа_2(ST(0))
https://www.cyberforum.ru/cgi-bin/latex.cgi?TOP\leftarrow TOP-1
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow temp
Эта команда разбивает текущую вершину стека на компоненты, ее операндом является вершина стека. Значение показателя степени замещает содержимое вершины стека, а затем дробная часть аргумента помещается в стек и становится новой вершиной стека. Действия команды FXTRACT обратные действиям команды FSCALE. Если в вершине стека находится некоторое число, то выполнение последовательно команд FXTRACT и FSCALE оставляет в вершине стека то же число. Но команда FSCALE не удаляет из стека показатель степени, так что теперь в стеке дополнительно окажется еще одно число.
Команда FABS
(вычисления абсолютного значения = ”Floating point ABSOLUTE value”)
Синтаксис команды:
FABS
Семантика команды: вычисления абсолютного значения вещественных чисел.
Псевдокод команды:
Знаковый_битhttps://www.cyberforum.ru/cgi-bin/latex.cgi?(ST(0))\leftarrow 0
Эта команда сбрасывает знаковый разряд числа в ST(0) (что соответствует положительному значению).
Команда FCHS
(изменения знака = ”Floating point CHANGE Sign”)
Синтаксис команды:
FCHS
Семантика команды: изменения знака вещественного числа.
Псевдокод команды:
Знаковый_битhttps://www.cyberforum.ru/cgi-bin/latex.cgi?(ST(0))\leftarrow NOT (Знаковый_бит(ST(0)))
Команда изменяет знаковый разряд числа в ST(0) на противоположный.
Кодировка трансцендентальных и прочих функций
Операция Опкод Действие
FCHSD9E0 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow\; -1\times ST(0)
FABS D9E1 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow абсолютное значение ST(0)
F2XM1 D9F0 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow(2^{ST(1)}-1)
FYL2X D9F1 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow ST(1) \times log_{2} (ST(0))
FPTAN D9F2 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(1)\leftarrow tg(ST(0)) ST(0)\leftarrow 1.0
FPATAN D9F3 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow Arctg(ST(1)/ST(0))
FXTRACT D9F4 
FPREM1 D9F5 
FPREM D9F8 
FYL2XP1 D9F9 https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow ST(1)\times log_{2}(ST(0)+1)
FSQRT D9FA https://www.cyberforum.ru/cgi-bin/latex.cgi?ST((0)\leftarrow \sqrt{ST(0)}
FSINCOS D9FB https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow Sin(ST(0)) ST(1)\leftarrow Cos(ST(0))
FRNDINT D9FC 
FSCALE D9FD https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow ST(0)\times 2^{ST(1)}
FSIN D9FE https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow Sin(ST(0))
FCOS D9FF https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow Cos(ST(0))
Команды сравнения
Операция сравнения чисел FPU отличается от целочисленной операции сравнения. Это отличие в большем количестве ситуаций и возможных результатов сравнения двух чисел. Числа могут быть:
  1. сравнимы
  2. несравнимы
  3. логически сравнимы
В первой группе сравниваемые числа могут быть больше, меньше, равны и т.д.
Во второй группе операнды не сравнимы. На пример, пытаются сравнить число и не число, число и денормализованное число и т.д.
В третью группу входят ситуации второй группы, но логически переосмысленные. Например, сравнивая число с денормализованным числом, представляют его как сравнение с нулём, или как сравнение числа и бесконечности.
Как видите третья группа – условна и зависит от постановки задачи, от её особенностей, и того, что имеет смысл, а что нет.
Всё это вызывает достаточно значительные проблемы. Если вы устанавливаете исключения на все случаи, то есть исключаете ситуацию появления «ненормализованных» чисел – то ваш код можно будет реализовывать как обычно, не обращая внимания на ситуации с образованием ненормализованных результатов. Иначе, потребуется дополнительный анализ после сравнения. При этом заметьте, что в вашей задаче может иметь смысл денормализованный операнд, но не имеет смысла бесконечность, или наоборот.
Команды FCOM (FCOMP, FCOMPP, FICOM, FICOMP)
(сравнение вещественных чисел = ”COMPARE Floating point values”)
Синтаксис команды:
FCOM <SRC>
Семантика команды: команда сравнения вещественных чисел.
Возможные варианты команды:
fcom mem
fcom st(i)
fcomp mem
fcomp st(i)
fcompp mem
fcompp st(i)
ficom mem
ficom st(i)
ficomp mem
ficomp st(i)
Псевдокод команды
:
CASE (relation of operands) OF
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)>SRC: C_{3},C_{2},C_{0}\leftarrow000
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)<SRC: C_{3},C_{2},C_{0}\leftarrow001
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)=SRC: C_{3},C_{2},C_{0}\leftarrow100
https://www.cyberforum.ru/cgi-bin/latex.cgi?Unordered: C_{3},C_{2},C_{0}\leftarrow111
В команде FCOM SRC всегда участвует вершина стека ST(0) и явно указанный регистр или операнд в памяти SRC. Команда FCOM SRC выполняет сравнение ST(0) с операндом SRC и устанавливает или сбрасывает биты состояния C3 и C0 (таблица 11.3.1). При этом указатель стека TOP не модифицируется, если это не команда FCOMP. Особой командой сравнения является FCOMPP, которая не имеет операндов. Она всегда сравнивает два верхних элемента стека ST(0) и ST(1), после сравнения они оба исчезают из стека. Команды FICOM/FICOMP сравнивают содержимое регистра ST(0) и 16- или 32-битной переменной SRC, считается что в SRC содержится целое число. В остальном команды FICOM/FICOMP эквивалентны командам FCOM/FCOMP.
Флаги состояния C3, C2 и C0 в FPU расположены на тех же местах, что и флаги нуля (ZF), паритета (PF) и переноса (CF) регистра EFLAGS.
Регистр состояния SWR B C3TOPC2C1C0
регистр EFLAGS SF ZF - AF - PF - CF
биты 7 6 5 4 3 2 1 0
Для опроса флагов состояния, программа считывает содержимое SWR и записывает его в память командой FSTSW (FNSTSW), которая сохраняет содержимое регистра SWR в 16-битной переменной, или регистре AX. При помощи команды SAHF содержимое флагов C3 и C0 заносится в регистр флагов микропроцессора, правда при этом флаг C1 попадает на неиспользуемый в EFLAGS 1-бит и его значение теряется. Вместо SAHF можно также использовать команду POPF.

Результат выполнения FCOM SRC
C0/CFC3/ZF C2/PF Значение
0 0 0 ST(0) > SRC
1 0 0 ST(0) < SRC
0 1 0 ST = SRC
1 1 1 ST(0) и SRC не могут быть сравнены
Таблица 11.3.1
Операция опкод Действие
FICOM m16int DE/2 Сравнить ST(0) c m16int
FICOM m32int DA/2 Сравнить ST(0) c m32int
FICOMP m16int DE/3 Сравнить ST(0) c m16int, вытолкнуть из стека
FICOMP m32int DA/3 Сравнить ST(0) c m32int, вытолкнуть из стека
Команда FUCOM (FUCOMP, FUCOMPP)
(сравнение вещественных чисел без учета порядка =
”Unordered COMPARE Floating point values”)
Синтаксис команды:
FUCOM<DEST>, <SRC>
Алгоритм работы: сравнения вещественных чисел без учета порядка.
Возможные варианты команды:
fucom st(0),st(i)
fucomp st(0),st(i)
fucompp st(0),st(i)
Псевдокод команды:
CASE (relation of operands) OF
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)>SRC: C_{3},C_{2},C_{0}\leftarrow 000
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)<SRC: C_{3},C_{2},C_{0}\leftarrow 001
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)=SRC: C_{3},C_{2},C_{0}\leftarrow 100
ENDCASE
IF ST(0) or SRC=QNaN, but not SnaN or unsupported format
https://www.cyberforum.ru/cgi-bin/latex.cgi?THEN C_{3},C_{2},C_{0}\leftarrow 111
ELSE;ST(0) or SRC=SnaN or unsupported format
#IA
IF FPUControlWord.IM=1
https://www.cyberforum.ru/cgi-bin/latex.cgi?THEN C_{3},C_{2},C_{0}\leftarrow 111
ENDIF
ENDIF
Команды FCOMI, FCOMIP, FUCOMI, FCOMIP появились в процессорах P6 и позволяют напрямую заносить результаты сравнения в регистр EFLAGS, не используя команды FSTSW AX/SAHF.
Операция Опкод Действие
FCOMI ST(0),ST(i) DBF0+i Сравнить ST(0) и ST(i), установить EFLAGS
FCOMIP ST(0),ST(i) DFF0+i Сравнить ST(0) и ST(i), установить EFLAGS, извлечь из стека
FUCOMI ST(0),ST(i) DBE8+i Сравнить без учета порядков значения в ST(0) и ST(i), установить EFLAGS
FUCOMIP ST(0),ST(i) DFE8+i Сравнить без учета порядков значения в ST(0) и ST(i), установить EFLAGS, извлечь из стека
Таблица 11.3.2
Результат выполнения FUCOM SRC
CF ZF PF Значение
0 0 0 ST(0) > SRC
1 0 0 ST(0) < SRC
0 1 0 ST = SRC
1 1 1 ST(0) и SRC не могут быть сравнены

Операция Опкод Действие Результат
FCOM st(i) D8DiСравнение вещественного значения, находящегося в ST(0), с оператором, находящемся в памяти или ST(i)Флаги FPU
FCOM m32fp D8/2 Флаги FPU
FCOM m64fp DC/2 Флаги FPU
FCOMP st(i) D8D8+iСравнение вещественного значения, находящегося в ST(0), с оператором, находящемся в памяти или ST(i), с выталкиванием вещественного значения с вершины стекаФлаги FPU
FCOMP m32fp D8/3 Флаги FPU
FCOMP m64fp DC/3 Флаги FPU
FCOMPP DED9Сравнивает вещественное значение, находящееся в ST(0) и ST(1), с оператором, находящемся в памяти или в ST(i), с выталкиванием вещественного значения из ST(0) и ST(1)Флаги FPU
FCOMI DBF0+i Сравнение вещественного значения, находящегося в ST(0), с оператором ST(i)Флаги CPU
FCOMIP DFF0+iСравнение вещественного значения, находящегося в ST(0), с оператором ST(i) с выталкиванием вещественного значения с вершины стекаФлаги CPU
FUCOMI DBE8+iНеупорядоченно сравнивает вещественное значение, находящееся в ST(0), с оператором ST(i)Флаги CPU
FUCOMIP DFE8+iНеупорядоченно сравнивает вещественное значение, находящееся в ST(0), с оператором ST(i) с выталкиванием вещественного значения с вершины стекаФлаги CPU
Кроме команд сравнения также доступны команды анализа FTST и FXAM.
Команда FTST
(сравнение вещественных чисел без учета порядка =
TEST Floating point values”)
Синтаксис команды:
FTST
Алгоритм работы: команда FTST сравнивает содержимое вершины стека ST(0) с нулём, и устанавливает коды условий.
Результат выполнения FTST
C0/CF C3/ZF C2/PF Значение
0 0 0 ST(0) > 0
1 0 0 ST(0) < 0
0 1 0 ST (0)= 0
1 1 1 ST(0) и 0 не могут быть сравнены
Таблица 11.3.3
Команда FXAM
(проверка числа на вершине стека = ”Floating point EXAMINE”)
Синтаксис команды:
FXAM
Алгоритм работы: проверка числа на вершине стека.
Команда FXAM устанавливает флаги регистра состояния от C0 до C3, показывая какое число находится на вершине стека.
C3/ZF C2/PF C1 C0/CF Значение
0 0 0 0 + ненормализованное
0 0 0 1 + NAN (не число)
0 0 1 0 - ненормализованное
0 0 1 1 - NAN
0 1 0 0 + нормализованное
0 1 0 1 https://www.cyberforum.ru/cgi-bin/latex.cgi?+\infty
0 1 1 0 - нормализованное
0 1 1 1 https://www.cyberforum.ru/cgi-bin/latex.cgi?-\infty
1 0 0 0 + 0
1 0 0 1 Пусто
1 0 1 0 - 0
1 0 1 1 Пусто
1 1 0 0 + денормализованное
1 1 0 1 пусто
1 1 1 0 - денормализованное
1 1 1 1 пусто
Если очень внимательно рассмотреть таблицу результата выполнения команды FXAM, то можно заметить, что C1 отвечает за знак (C1=0 – знак положительный, C1=1 – знак отрицательный). Если число конечное (ноль, ненормализованное число, нормализованное число, денормализованное число) – С0 = 0, если число неконечное (нечисло, бесконечность, пусто) – С0 = 1.
C1=0 C1=1 C3/ZF C2/PF C0/CF
+ненормализованное -ненормализованное 0 0 0
+нормализованное -нормализованное 0 1 0
+0 -0 1 0 0
+денормализованное -денормализованное 1 1 0
+NAN (нечисло) -NAN (нечисло) 0 0 1
https://www.cyberforum.ru/cgi-bin/latex.cgi?+\infty https://www.cyberforum.ru/cgi-bin/latex.cgi?-\infty 0 1 1
Пусто Пусто 1 0 1
Пусто Пусто 1 1 1
Команда FCMOVcc
(Условная пересылка данных =”Floating point Condition MOVE”)
Синтаксис команды:
FCMOVcc <DEST>, <SRC>
Семантика команды: условная пересылка данных.
Возможные варианты команды:
fcmove st(0),st(i)
fcmovne st(0),st(i)
fcmovb st(0),st(i)
fcmovbe st(0),st(i)
fcmovnb st(0),st(i)
fcmovnbe st(0),st(i)
fcmovu st(0),st(i)
fcmovnu st(0),st(i)
Псевдокод команды
:
IF condition TRUE
https://www.cyberforum.ru/cgi-bin/latex.cgi?THEN ST(0)\leftarrow ST(i)
ENDIF
Это набор команд, каждая из которых копирует содержимое регистра ST(i)) в ST(0), если выполняется соответствующее условие. Реально, каждое условие соответствует тем или иным значениям флагов регистра EFLAGS, но после команд fcom ; (или другие команды сравнения)
Assembler
1
2
3
fstsw ax
sahf
fcmovcc
в регистр FLAGS загружаются флаги С0, С1 и С3, и последующая команда из набора FCMOVcc приобретает смысл обработки результата предыдущего сравнения.

Операция Опкод Значения флагов Действие после FCOM
FCMOVB ST(0),ST(i) DACi ZF = 1 если равно
FCMOVE ST(0),ST(i) DAC8+i ZF = 0 если не равно
FCMOVBE ST(0),ST(i) DADi CF = 1 если меньше
FCMOVU ST(0),ST(i) DAD8+i CF = 1 и ZF = 1 если меньше или равно
FCMOVNB ST(0),ST(i) DBCi CF = 0 если не меньше
FCMOVNE ST(0),ST(i) DBC8+i CF = 0 и ZF = 0 если не меньше или равно
FCMOVNBE ST(0),ST(i) DBDi PF = 1 если несравнимы
FCMOVNU ST(0),ST(i) DBD8+i PF = 0 если сравнимы

Операция Опкод Действие
FTST D9E4 Сравнить ST(0) с 0
FXAM D9E5 Классифицировать значение в ST(0)
FSTSW m2byte 9BDD/7 
FSTSW AX 9BDFE0 
FNSTSW m2byte DD/7 
FNSTSW AX DFE0 
Трансцендентальные функции
Числа, не удовлетворяющие никакому алгебраическому уравнению с целыми коэффициентами, называются трансцендентальными. https://www.cyberforum.ru/cgi-bin/latex.cgi?\pi=3,141592 и https://www.cyberforum.ru/cgi-bin/latex.cgi?e=2,71828 – трансцендентальные числа. Если https://www.cyberforum.ru/cgi-bin/latex.cgi?a и https://www.cyberforum.ru/cgi-bin/latex.cgi?b – положительные алгебраические числа, то число https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{a}(b) либо рациональное, либо трансцендентальное. Числа https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{2}3, https://www.cyberforum.ru/cgi-bin/latex.cgi?lg(5), https://www.cyberforum.ru/cgi-bin/latex.cgi?ln(27) и тому подобные – трансцендентальны.
Десятичный логарифм любого целого числа, не изображаемого единицей с нулями (1, 10, 100, 0,1, 0,01) – трансцендентальное число.
Трансцендентальные функции – это аналитические функции, не являющиеся алгебраическими. К элементарным трансцендентным функциям относятся:
  • тригонометрические (https://www.cyberforum.ru/cgi-bin/latex.cgi?sin, https://www.cyberforum.ru/cgi-bin/latex.cgi?cos, https://www.cyberforum.ru/cgi-bin/latex.cgi?tg…);
  • обратные тригонометрические (https://www.cyberforum.ru/cgi-bin/latex.cgi?arcsin, https://www.cyberforum.ru/cgi-bin/latex.cgi?arccos, https://www.cyberforum.ru/cgi-bin/latex.cgi?arctg…);
  • логарифмические функции (https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{2}x, https://www.cyberforum.ru/cgi-bin/latex.cgi?lg(x), https://www.cyberforum.ru/cgi-bin/latex.cgi?ln(x));
  • показательные функции (https://www.cyberforum.ru/cgi-bin/latex.cgi?x^{y}, https://www.cyberforum.ru/cgi-bin/latex.cgi?2^{y}, https://www.cyberforum.ru/cgi-bin/latex.cgi?10^{x}, https://www.cyberforum.ru/cgi-bin/latex.cgi?e^{x});
  • гиперболические функции (https://www.cyberforum.ru/cgi-bin/latex.cgi?sh, https://www.cyberforum.ru/cgi-bin/latex.cgi?ch, https://www.cyberforum.ru/cgi-bin/latex.cgi?th, …);
  • обратные гиперболические (https://www.cyberforum.ru/cgi-bin/latex.cgi?arcsh, https://www.cyberforum.ru/cgi-bin/latex.cgi?arch, https://www.cyberforum.ru/cgi-bin/latex.cgi?arcth…);
FPU не реализует их все. В нём представлены только основные функции, которые необходимы для вычисления всех остальных возможных.

Тригонометрические функции
Команда FCOS

(вычисление косинуса =”Floating point COSINE)
Синтаксис команды:
FCOS
Семантика команды: команда вычисления косинуса.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?IF |ST(0)|< 2^{63}
https://www.cyberforum.ru/cgi-bin/latex.cgi?THEN C_{2}\leftarrow 0
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow Cos(ST(0))
ELSE;операнд выходит за пределы
https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2}\leftarrow 1
ENDIF
Косинус числа, находящегося в ST(0). Операнд считается заданным в радианах и имеет пределы 263 и -263. Если операнд выходит за эти пределы, флаг https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2} = 1, а ST(0) не изменяется.
Команда FSIN
(вычисление синуса =”Floating point SINE)
Синтаксис команды:
FSIN
Семантика команды: команда вычисления синуса.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?IF |ST(0)|<2^{63}
THEN C2https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow Sin(ST(0))
ELSE;операнд выходит за пределы
https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2}\leftarrow 1
ENDIF
Синус числа, находящегося в ST(0). Операнд считается заданным в радианах и имеет пределы 263 и -263. Если операнд выходит за эти пределы, флаг https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2} = 1, а содержимое ST(0) не изменяется.
Имея вычисленный https://www.cyberforum.ru/cgi-bin/latex.cgi?sin^{2}(x), легко получить https://www.cyberforum.ru/cgi-bin/latex.cgi?cos^{2}(x): https://www.cyberforum.ru/cgi-bin/latex.cgi?sin^{2}(x)+cos^{2}(x)=1
  • https://www.cyberforum.ru/cgi-bin/latex.cgi?sin(2x) = 2 sin(x) cos(x)
  • https://www.cyberforum.ru/cgi-bin/latex.cgi?cos^{2}(\frac{x}{2})=\frac{cos(x)+1}{2}
  • https://www.cyberforum.ru/cgi-bin/latex.cgi?cos(2x) = cos^{2}(x)-sin^{2}(x)
Команда FSINCOS
(вычисление косинуса и синуса числа =”Floating point SINE and COSINE)
Синтаксис команды:
FSINCOS
Семантика команды: команда вычисления косинуса и синуса числа.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?IF |ST(0)|<2^{63}
https://www.cyberforum.ru/cgi-bin/latex.cgi?THEN C_{2}\leftarrow 0
https://www.cyberforum.ru/cgi-bin/latex.cgi?temp\leftarrow Cos(ST(0))
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow Sin(ST(0))
https://www.cyberforum.ru/cgi-bin/latex.cgi?TOP\leftarrow TOP-1
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow temp
ELSE;операнд выходит за пределы
https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2}\leftarrow 1
ENDIF
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrowугол в радианах, результат вычислений в https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)=Cos(угол) и https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(1)=Sin(угол)
Команда FPTAN
(вычисление частичного тангенса=”Floating point Partial TANGENT”)
Синтаксис команды:
FPTAN
Семантика команды: команда вычисления частичного тангенса числа.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?IF |ST(0)|<2^{63}
https://www.cyberforum.ru/cgi-bin/latex.cgi?THEN C_{2}\leftarrow 0
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow tg(ST(0))
https://www.cyberforum.ru/cgi-bin/latex.cgi?TOP\leftarrow TOP-1
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow 1.0
ELSE;операнд выходит за пределы
https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{2}\leftarrow 1
ENDIF
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow X\; ST(1)\leftarrow Y, где https://www.cyberforum.ru/cgi-bin/latex.cgi?Y/X = tg (\alpha ).
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow ST(1)/ST(0)Исходное число – угол https://www.cyberforum.ru/cgi-bin/latex.cgi?\alpha, выраженный в радианах, значение которого должно быть в интервале https://www.cyberforum.ru/cgi-bin/latex.cgi?0 < \alpha < \pi/4, помещается в вершину стека. Уменьшить угол https://www.cyberforum.ru/cgi-bin/latex.cgi?\alpha до правильного значения можно с помощью команды FPREM. Результатом является отношение https://www.cyberforum.ru/cgi-bin/latex.cgi?Y/X, которое равно тангенсу угла https://www.cyberforum.ru/cgi-bin/latex.cgi?\alpha; https://www.cyberforum.ru/cgi-bin/latex.cgi?Y передается в ST(0), а затем в ST(0) помещается https://www.cyberforum.ru/cgi-bin/latex.cgi?X.
Вычисляется тангенс. Результат помещается в ST(0), после чего в ST(0) помещается 1, так что: ST(0) = 1, ST(1) = tg(ST(0)). Единица в ST(0) была нужна для дальнейших вычислений значений sin/cos (инструкции fsin/fcos появились позже, до их появления https://www.cyberforum.ru/cgi-bin/latex.cgi?cos(x) приходилось вычислять по формуле [LATEX]\frac{1}{\sqrt{1+tg^{2}(x)}}, а https://www.cyberforum.ru/cgi-bin/latex.cgi?sin(x) по формуле [LATEX]\frac{tg(x)}{\sqrt{1+tg^{2}(x)}}
Команда FPATAN
(вычисление частичного арктангенса =
Floating point Partial ARCTANGENT”)
Синтаксис команды:
FPATAN
Семантика команды: команда вычисления частичного арктангенса от вещественного числа.
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?IF 0\leq |ST(1)|<|ST(0)|<+\infty
THEN https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(1)\leftarrow arctg(ST(1)/ST(0))
PopRegisterStack
ENDIF
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(0)\leftarrow arctg(\frac{Y}{X})=arctg(\frac{ST(1)}{ST(0)})

Эта функция дополняет предыдущую, FPTAN. Команда FPATAN вычисляет угол в соответствии с отношением чисел ST(1) и ST(0). Она извлекает из стека число X, а затем записывает результирующий угол вместо числа Y в качестве новой вершины стека. Исходные значения должны подчиняться неравенству https://www.cyberforum.ru/cgi-bin/latex.cgi?0<Y<X<+\infty.
Вычисляет арктангенс числа ST(1)/ST(0). Результат записывается в ST(1), а ST(0) выталкивается. Результат имеет знак ST(1) и меньше числа p по абсолютной величине.
Для вычисления https://www.cyberforum.ru/cgi-bin/latex.cgi?arcsin(x) и https://www.cyberforum.ru/cgi-bin/latex.cgi?arccos(x) используется свойство https://www.cyberforum.ru/cgi-bin/latex.cgi?cos^{2}(x)+sin^{2}(x)=1.
https://www.cyberforum.ru/cgi-bin/latex.cgi?tg(x)=\frac{sin(x)}{\sqrt{1-sin^{2}(x)}}=\frac{\sqrt{1-cos^{2}(x)}}{cos(x)}
Обратные тригонометрические функции
https://www.cyberforum.ru/cgi-bin/latex.cgi?arcsin(x)=arctg(\frac{x}{\sqrt{1-x^{2}}})
https://www.cyberforum.ru/cgi-bin/latex.cgi?arccos(x)=arctg(\sqrt{\frac{1-x}{1+x}})
https://www.cyberforum.ru/cgi-bin/latex.cgi?arcsec(x)=arccos(\frac{1}{x})

Логарифмические функции
Команда FYL2X
(вычисление https://www.cyberforum.ru/cgi-bin/latex.cgi?Y \times log_{2}X = ”https://www.cyberforum.ru/cgi-bin/latex.cgi?Compute Y \times log_{2}(X)”)
Синтаксис команды:
FYL2X
Алгоритм работы: вычисление https://www.cyberforum.ru/cgi-bin/latex.cgi?Y \times log_{2}X
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(1)\leftarrow ST(1)\times log_{2}(ST(0))
PopRegisterStack
Эта функция выполняет операцию логарифмирования. Она берет логарифм по основанию 2 от содержимого ST(0) и затем умножает его на содержимое ST(1). Команда FYL2X извлекает из стека число X и замещает результат числом Y. Исходные числа должны удовлетворять следующим соотношениям:
https://www.cyberforum.ru/cgi-bin/latex.cgi?0< X<+\infty и https://www.cyberforum.ru/cgi-bin/latex.cgi?-\infty <Y<+\infty
Результат размещается в ST(1), а ST(0) выталкивается из стека. При этом ST(0)>0, если ST(0) = 0, тогда результат (ZM = 1) равен бесконечности со знаком, обратным ST(1).
Логарифмические функции на основе FYL2X
А что делать, если требуется вычислить логарифм по основанию, не равному 2? С помощью формулы https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{Y}X=\frac{log_{2}X}{log_{2}Y} вычисляется логарифм числа https://www.cyberforum.ru/cgi-bin/latex.cgi?X по основанию https://www.cyberforum.ru/cgi-bin/latex.cgi?Y. Команды загрузки FLDLG2 (загрузка https://www.cyberforum.ru/cgi-bin/latex.cgi?lg(2)) и FLDLN2 (загрузка https://www.cyberforum.ru/cgi-bin/latex.cgi?ln(2)) позволяют работать с десятичными (бригговыми) и натуральными (неперовыми или гиперболическими) логарифмами:
https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{2}X = FYL2X(x);
https://www.cyberforum.ru/cgi-bin/latex.cgi?ln(X) = ln(2)\times log_{2}X = FYL2X(ln(2), X) = FYL2X (FLDLN2,X)
https://www.cyberforum.ru/cgi-bin/latex.cgi?lg(X) = lg(2)\times log_{2}X = FYL2X(lg(2), X) = FYL2X (FLDLG2,X)
Команда FYL2XP1
(вычисление https://www.cyberforum.ru/cgi-bin/latex.cgi?Y \times log_{2}(X+1) = ”https://www.cyberforum.ru/cgi-bin/latex.cgi?Compute Y \times log_{2}(X+1)”)
Синтаксис команды:
FYL2XP1
Алгоритм работы: вычисление https://www.cyberforum.ru/cgi-bin/latex.cgi?Y \times log_{2}(X+1)
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(1)\leftarrow ST(1)\times log_{2}(ST(0)+1.0)
PopRegisterStack
Эта функция идентична функции FYL2X, за исключением того, что к X прибавляется 1. Функция FYL2XP1 накладывает более жесткие ограничения на X и предназначена для вычисления логарифмов чисел, значения которых очень близки к 1. Эта функция дает наиболее высокую точность, если https://www.cyberforum.ru/cgi-bin/latex.cgi?0 < |X| < 1-\frac{\sqrt{2}}{2}.
Вычисляет https://www.cyberforum.ru/cgi-bin/latex.cgi?ST(1)\times log_{2}(ST(0)+1). ST(1) равен результату, после чего ST(0) выталкивается из стека. При этом первоначальный ST(0) принадлежит (https://www.cyberforum.ru/cgi-bin/latex.cgi?-a,a), где https://www.cyberforum.ru/cgi-bin/latex.cgi?a = 1-\frac{1}{\sqrt{2}}. Наличие этой команды обусловлено тем, что она даёт большую точность, чем FYL2X для суммы ST(0)+1 для чисел, близких к нулю.
Команды загрузки констант
Команды загружают в стек заранее известные величины. Все команды загрузки констант не имеют операндов и могут работать только с ST(0).
Операция Опкод Действие
FLD1 D9E8 Команда загрузки единицы (+1.0)
FLDL2T D9E9 Команда загрузки https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{2}(10)=3,32192809488736234780
FLDL2E D9EA Команда загрузки https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{2}(e)= 1,44269504088896340725
FLDPI D9EB Команда загрузки числа https://www.cyberforum.ru/cgi-bin/latex.cgi?\pi = 3,141593265358979323
FLDLG2 D9EC Команда загрузки https://www.cyberforum.ru/cgi-bin/latex.cgi?lg(2)=0,3010299956639811952202
FLDLN2 D9ED Команда загрузки https://www.cyberforum.ru/cgi-bin/latex.cgi?ln(2)=0,6931471805599453094172
FLDZ D9EE Команда загрузки нуля (+0.0)
но если присмотреться внимательно
FP-опкод Описание число эквивалент
FLDL2EПомещает константу = https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{2}(e) в стек1,4426950408889634073599246810019 https://www.cyberforum.ru/cgi-bin/latex.cgi?=1/ln(2)
FLDL2TПомещает константу = https://www.cyberforum.ru/cgi-bin/latex.cgi?log_{2}(10) в стек 3,3219280948873623478703194294894https://www.cyberforum.ru/cgi-bin/latex.cgi?=1/lg(2)
FLDLG2Помещает константу = https://www.cyberforum.ru/cgi-bin/latex.cgi?lg(2) в стек 0,30102999566398119521373889472449 https://www.cyberforum.ru/cgi-bin/latex.cgi?=1/log_{2}(10)
FLDLN2Помещает константу = https://www.cyberforum.ru/cgi-bin/latex.cgi?ln(2) в стек0,69314718055994530941723212145818https://www.cyberforum.ru/cgi-bin/latex.cgi?=1/log_{2}(e)
Команды управления FPU
Команды управления ничего не вычисляют, однако они необходимы для управления FPU. Обычно эти команды требуются в подпрограммах и процедурах прерываний, в которых происходит совместная работа блоков IEU и FPU, а также при обработке ошибок блока FPU. Некоторые команды (например, FINIT/FNINIT) имеют альтернативную мнемонику с символом N, предназначенные для использования в тех случаях, когда команда WAIT не нужна.
Команда инициализации FINIT/FNINIT (FPU INITIALIZE) сбрасывает FPU в состояние, в которое он попадает при включении питания. Рекомендуется использовать эту команду перед обращением к FPU. В результате FINIT:
  • rc=0 (режим округления к ближайшему числу);
  • флаги особых ситуаций в регистре SWR сброшены;
  • флаги запрета прерываний в регистре CWR по особым ситуациям установлены;
  • TOP=7.
Команда FSTSW/FNSTSW (FPU STORE Status Word) записывает в 16-битную ячейку памяти значение регистра состояния FPU. Допускается использование регистра AX.
Команда FSTCW/FNSTCW (FPU STORE Control Word) записывает в 16-битную ячейку памяти значение регистра управления FPU.
Команда FFREE ST(i) (FPU FREE register) отмечает атрибут регистра ST(i) в регистре TW как незанятый.
Команда FCLEX (FPU CLEAR EXCEPTION) сбрасывает признаки особых ситуаций в регистре SWR.

Рис. 11.3.3. Структура области памяти с рабочей средой сопроцессора
Команда FLDCW SRC (FPU LOAD Control Word) записывает в регистр RCW содержимое 16-битной ячейки памяти. Подобная команда для записи в регистр RSW не предусмотрена.
Пустая команда FNOP (FPU Not OPERATION) используется для синхронизации совместных действий процессора и FPU и в отладочных целях. Заменяет некоторые команды управления, унаследованные от i8087, i80287 недействительные в P6.
Команды FDECSTP/FINCSTP (FPU DECREMENT/INCREMENT Stack-Top Pointer) уменьшают/увеличивают величину TOP на единицу, «передвигая» по кольцу значения между регистрами ST(i).
Команда FSTENV DEST (FPU STORE ENVIRONMENT) считывает в ячейку DEST (m14byte, если use16 либо m28byte, если use32) в системной памяти содержимое регистров TW, RSW, RCW, FIP, FDP. Устанавливает в RCW флаги запрета прерываний по особым ситуациям.
Команда FLDENV SRC (FPU LOAD ENVIRONMENT) записывает в FPU образ его регистров из ячейки SRC (m14byte, если use16 либо m28byte, если use32) системной памяти.
Операция Опкод Действие
FWAIT/WAIT 9B 
FNOP D9D0 
FDECSTP D9F6 TOPhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow(TOP-1)& 7
FINCSTP D9F7 TOPhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow(TOP+1)& 7
FLDCW m2byte D9/5
FCLEX 9BDBE2 
FNCLEX DBE2 
FINIT 9BDBE3 
FNINIT DBE3RCWhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow37Fh RSWhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 TWhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0FFFFh FDPhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 FIPhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 LastInstructionOpcodehttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
FFREE ST(i) DDCi TAG(i)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow11b
FLDENV m14/28byte D9/4 RCWhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowSRC, RSWhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow(SRC+2), TWhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow(SRC+4), FIPhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow(SRC+6), FDPhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow(SRC+10)
FSAVE m94/108byte 9BDD/5 
FNSAVE m94/108byte DD/5 
FSTENV DEST 9BD9/6 
FSTENV m14/28byte D9/6DESThttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowRCW,(DEST+2)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowRSW,(DEST+4)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowTW,(DEST+6)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowFIP, (DEST+10)https://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowFDP
Команда FSAVE DEST (FPU SAVE State) считывает в ячейку DEST (m94byte, если use16 либо m108byte, если use32) в системной памяти данные из FPU целиком, включая R0-R7, и выполняет FINIT. За первыми 14/28 байтами окружения следуют копии R0-R7.
Команда FRSTOR SRC (FPU RESTORE State) восстанавливает состояние FPU полностью, в соответствии с образом из ячейки SRC (m94byte, если use16 либо m108byte, если use32) в системной памяти
Команда FWAIT/WAIT останавливает центральный процессор до завершения текущей операции в FPU. В P6 имеет смысл только при обработке аппаратных прерываний, возникающих в связи с ошибками в блоке FPU.
Опкоды основных команд FPU
Для команд с операндом st(i) используется режим регистровой адресации (Mod=11 R/M=st(i)), для команд с другими операндами выбран режим прямой адресации (Mod=00 R/M=101).
команда m32fp m64fp m80fp st(i) m16int m32int m64int m80bcd
FADD D805 DC05  D8Ci DE05 DA05  
FMUL D80D DC0D  DCC8+i DE0D DA0D  
FCOM D815 DC15  D8Di DE15 DA15  
FCOMP D81D DC1D  D8D8+i DE1D DA1D  
FSUB D825 DC25  D8Ei DE25 DA25  
FDIV D835 DC35  D8Fi DE35 DA35  
FLD D905 DD05 DB2D D9Ci DF05* DB05 DF2D DF25**
FST D915 DD15  DDDi DF15 DB15  
FSTP D91D DD1D DB3D DDD8+i DF1D DB1D DF3D DF35
FADDP   DECi     
FMULP   DEC8+i     
FSUBP   DEE8+i     
FDIVP   DEF8+i     
FSUBRP   DEEi     
FDIVRP   DEFi     
*Под командой FLD mXXint подразумевается команда FILD mXXint
**Под командой FLD m80bcd подразумевается команда FBLD m80bcd
Формирование программного кода для эмуляции команд
с плавающей запятой
Опция /E указывает ассемблеру masm на генерацию кода инструкций для реализацию вычислений с плавающей запятой, эмулирующей сопроцессор Intel x87. Эта опция была введена во времена микропроцессоров Intel 8086 и Intel 80286 для работы на компьютерах, которые не всегда комплектовались сопроцессором. Если программист намеревался на такой машине выполнить программу, использующую инструкции FPU, и при этом располагал библиотеками математических эмуляторов типа тех, которые поставляются с языками высокого уровня (Pascal, Fortran, C/C++/C#), то он должен был применить опцию /E в процессе ассемблирования, а затем скомпоновать полученный в результате объектный файл с библиотекой математических эмуляторов. Такая библиотека содержала стандартные программы, эмулирующие инструкции Intel x87 для выполнения вычислений с плавающей запятой.
Пример указания на формирование эмулирующего кода для любых обнаруженных в программе file.asm инструкций с плавающей запятой:
Code
1
2
ml file /E
link file,,,math.lib
В контрольных вопросах и упражнениях пользователя с целью обучения просят написать подпрограммы, эмулирующие выполнение сложения, вычитания, умножения и деление чисел с плавающей запятой.
Подпрограммы должны также обрабатывать ошибки, связанные с переполнением и потерей значимости. Желательно, чтобы пользователь написал такие подпрограммы самостоятельно, а потом, убедившись в их работоспособности, сравнил бы свои программы с программами, использовавшими библиотеку математических эмуляторов.
При написании программ для эмуляции операций над числами с плавающей запятой операнды помещаются в регистры, первый регистр содержит порядок, второй – старшие разряды мантиссы, третий – младшие разряды мантиссы.
Перед выполнением подпрограммы первый операнд хранится в регистрах EAX, EBX, ECX. Второй операнд, если он есть, помещается в регистры EDX, ESI, EDI.
По окончании работы подпрограммы результат помещается в регистры EAX, EBX, ECX.
Условие переполнения и потери значимости обрабатывается подпрограммой OUFLW, которая проверяет, имеет ли место переполнение при возврате из подпрограммы. Регистры результата содержат наибольшее возможное положительное или отрицательное число.
Контрольные вопросы и упражнения
  1. Напишите подпрограмму, эмулирующую выполнение сложение чисел с плавающей запятой. Подпрограмма должна обрабатывать ошибки, связанные с переполнением и потерей значимости.
  2. Напишите подпрограмму, эмулирующую выполнение вычитание чисел с плавающей запятой. Подпрограмма должна обрабатывать ошибки, связанные с переполнением и потерей значимости.
  3. Напишите подпрограмму, эмулирующую выполнение умножение чисел с плавающей запятой. Подпрограмма должна обрабатывать ошибки, связанные с переполнением и потерей значимости.
  4. Напишите подпрограмму, эмулирующую выполнение деление чисел с плавающей запятой. Подпрограмма должна обрабатывать ошибки, связанные с переполнением и потерей значимости.
  5. Напишите подпрограмму, эмулирующую изменение знака числа с плавающей запятой. Подпрограмма должна обрабатывать ошибки, связанные с переполнением и потерей значимости.
  6. Напишите подпрограмму, эмулирующую извлечение квадратного корня из числа с плавающей запятой. Подпрограмма должна обрабатывать ошибки, связанные с переполнением и потерей значимости.
  7. Пусть следующие 16-битные числа представляют короткие вещественные числа:
    1. 0CA5B2000h
    2. 3C630000h
    3. 4C341200h
    Определите десятичные эквиваленты этих чисел.
  8. Преобразуйте следующие десятичные числа в короткий вещественный формат и запишите ответы в шестнадцатеричной системе:
    1. https://www.cyberforum.ru/cgi-bin/latex.cgi?-123450000
    2. https://www.cyberforum.ru/cgi-bin/latex.cgi?-148,4375\cdot 10^{-3}
    3. https://www.cyberforum.ru/cgi-bin/latex.cgi?1,2345625\cdot 10^{4}
  9. Напишите программу, которая преобразует беззнаковое десятичное число в эквивалентное короткое вещественное число. Считаем, что целая часть, содержащая до 10 десятичных цифр, находится в массиве INTARRAY, дробная часть, которая тоже содержит до 10 десятичных цифр, находится в массиве FRARRAY, а результат необходимо запомнить в переменной REALVAR. Зарезервируйте в качестве рабочей области массив WORK из 10 байтов.
  10. Пусть N вещественных чисел хранятся в коротком вещественном формате, начиная с метки REALARRAY. Напишите программу, которая умножает сумму положительных чисел на сумму отрицательных чисел и запомните результат в переменной RESULT.
  11. Напишите программу, которая вычисляет https://www.cyberforum.ru/cgi-bin/latex.cgi?sin (\theta) и https://www.cyberforum.ru/cgi-bin/latex.cgi?tg (\theta), где https://www.cyberforum.ru/cgi-bin/latex.cgi?0\leq  \theta\leq \frac{\pi}{2}. Считайте, что переменная THETA содержит угол в коротком вещественном формате, а результат запоминается в длинном вещественном формате.
Миниатюры
Электронный учебник   Электронный учебник  
Изображения
  
6
Закрытая тема Создать тему
Новые блоги и статьи
сукцессия 33. открытые вопросы от клауде
anaschu 19.07.2026
"Что накопилось за эту часть А — тринадцать правок, из которых шесть пришли из ваших вопросов и каждая оказалась реальной ошибкой, а не калибровкой: односторонний симбиоз, отсутствующий листопад,. . .
32 сукцессия
anaschu 19.07.2026
сукцессия 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не «подкручивает» сходимость —. . .
сукцессия 31: модель микоризы - это модель ещё нескольких явлений, социальных и экономических
anaschu 18.07.2026
Теория «Всего»: апдейт v1. 1. 2 — 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не. . .
сукцессия 30. Массив проверяющих друг друга моделей
anaschu 18.07.2026
Архитектура сети взаимопроверяющих моделей микоризной сукцессии (v2. 0) Развитие тензорного ОДУ-ядра и создание кросс-платформенного калибровочного полигона Уважаемые коллеги! В продолжение. . .
Грибы - это женщины, деревья - это мужчины. Анти инь янь для союза мужчины и женщины.
anaschu 18.07.2026
ГЛАВНЫЙ НАУЧНО-ФИЛОСОФСКИЙ ВЫВОД: Сексуально-Репродуктивный Капитализм против Государства Моногамии Коллеги, мы вышли на финишную прямую 20-мерного ОДУ-моделирования вековой сукцессии (ветка. . .
Текстовый слайдер с нумерацией страниц и кроссбраузерность.
russiannick 18.07.2026
Один мой друг написал текстовый слайдер с нумерацией страниц. Сегодня я расскажу как он умудрился подружить его с кроссбраузерностью. Очевидно сложно угодить с шириной каждому браузеру. Один крадет. . .
Грибы - это мемы, дерево - это человек. Применение микоризной модели к теории меметики Докинза.
anaschu 18.07.2026
Меметический изоморфизм теории «всего»: Грибная сукцессия как модель эволюции идей Докинза Базовый код системы ОДУ микоризной сукцессии описывает не просто биологию, а универсальную. . .
Грибы - это корпорации, деревья - это государства. Механизм массонского захвата власти
anaschu 18.07.2026
Макроэкономический изоморфизм теории «всего»: Грибная сукцессия как модель транснационального капитализма Базовый код системы ОДУ микоризной сукцессии описывает не просто биологию, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru