Система команд сопроцессора включает в себя около 80 машинных команд, включающих в себя
- команды передачи данных;
- команды сравнения данных;
- арифметические команды;
- команды трансцендентных функций;
- команды управления сопроцессором.
Мнемоническое обозначение команд сопроцессора характеризует особенности их работы и в связи с этим может представлять определенный интерес. Поэтому коротко рассмотрим основные моменты образования названий команд:
- все мнемонические обозначения начинаются с символа f (float);
- вторая буква мнемонического обозначения определяет тип операнда в памяти, с которым работает команда: - i — целое двоичное число; - b — целое десятичное число; - отсутствие буквы — вещественное число;
- последняя буква мнемонического обозначения команды р означает, что последним действием команды обязательно является извлечение операнда из стека;
- последняя или предпоследняя буква r (reversed) означает реверсивное следование операндов при выполнении команд вычитания и деления, так как для них важен порядок следования операндов.
Система команд сопроцессора отличается большой гибкостью в выборе вариантов задания команд, реализующих определенную операцию, и их операндов. Минимальная длина команды сопроцессора — 2 байта. Все команды сопроцессора оперируют регистрами стека сопроцессора. Если операнд в команде не указывается, то по умолчанию используется вершина стека сопроцессора (логический регистр st(0)). Если команда выполняет действие с двумя операндами по умолчанию, то эти операнды – регистры st(0) и st(1).
Команды передачи данных
Группа команд передачи данных предназначена для организации обмена между регистрами стека, вершиной стека сопроцессора и ячейками оперативной памяти. Команды этой группы имеют такое же значение для процесса программирования сопроцессора, как и команда mov основного процессора. С помощью этих команд осуществляются все перемещения значений операндов в сопроцессор и из него. По этой причине для каждого из трех типов данных, с которыми может работать сопроцессор, существует своя подгруппа команд передачи данных. Собственно на этом уровне все его умения по работе с различными форматами данных и заканчиваются. Главной функцией всех команд загрузки данных в сопроцессор является преобразование их к единому представлению в виде вещественного числа расширенного формата. Это же касается и обратной операции — сохранения в памяти данных из сопроцессора.
Команды передачи данных можно разделить на следующие группы:
- команды передачи данных в вещественном формате;
- команды передачи данных в целочисленном формате;
- команды передачи данных в двоично-десятичном формате.
Основными командами передачи данных являются
- команда FLD (загрузка данных в вершину стека сопроцессора);
- команда FST (сохранение вершины стека сопроцессора в память)
и их модификации.
Команды передачи данных вещественного типа
Используются в случае если операнд, применяемый в команде, имеет вещественный тип (4, 8 или 10-байтный).
Команда | Операнды | Пояснение | Описание |
FLD | src | TOPSWR-=1; ST(0)=src; | Загрузка операнда в вершину стека |
FST | dst | dst=ST(0); | Сохранение вершины стека в память |
FSTP | dst | dst=ST(0); TOPSWR+=1; | Сохранение вершины стека в память с выталкиванием |
FXCH | ST(i) | ST(0) ↔ ST(i) | Обмен значений ST(0) и ST(i) |
Команды передачи данных целого типа Используются в случае если операнд, применяемый в команде, имеет целый тип (1, 2, 4 или 8-байтный).
Команда | Операнды | Пояснение | Описание |
FILD | src | TOPSWR-=1; ST(0)=src; | Загрузка операнда в вершину стека |
FIST | dst | dst=ST(0); | Сохранение вершины стека в память |
FISTP | dst | dst=ST(0); TOPSWR+=1; | Сохранение вершины стека в память с выталкиванием |
Команды передачи данных двоично-десятичного типа Используются в случае если операнд, применяемый в команде, представлен в двоично-десятичной системе счисления (1, 2, 4 или 8-байтный).
Команда | Операнды | Пояснение | Описание |
FBLD | src | TOPSWR-=1; ST(0)=src; | Загрузка операнда в вершину стека |
FBSTP | dst | dst=ST(0); TOPSWR+=1; | Сохранение вершины стека в память с выталкиванием |
Команды загрузки констант Команды загрузки констант не имеют операндов и загружают соответствующее константное значение в вершину стека сопроцессора.
Команда | Пояснение | Описание |
FLDZ | TOPSWR-=1; ST(0)=0; | Загрузка 0 |
FLD1 | TOPSWR-=1; ST(0)=1; | Загрузка 1 |
FLDPI | TOPSWR-=1; ST(0)=3.1415926535; | Загрузка π |
FLDL2T | TOPSWR-=1; ST(0)=3.3219280948; | Загрузка log210 |
FLDL2E | TOPSWR-=1; ST(0)=1.4426950408; | Загрузка log2e |
FLDLG2 | TOPSWR-=1; ST(0)=0.3010299956; | Загрузка lg 2 |
FLDLN2 | TOPSWR-=1; ST(0)=0.6931471805; | Загрузка ln 2 |
Команды сравнения данных
Команды данной группы выполняют сравнение значений числа в вершине стека и операнда, указанного в команде.
Команды сравнения данных вещественного типа
Команда | Операнды | Пояснение | Описание |
FCOM FUCOM | src | ST(0) - src | Вещественное сравнение |
FCOMP FUCOMP | src | ST(0) - src; TOPSWR+=1; | Вещественное сравнение с выталкиванием |
FCOMPP FUCOMPP | - | ST(0) - ST(1); TOPSWR+=2; | Вещественное сравнение с двойным выталкиванием |
FCOMI FUCOMI | ST, ST(i) | ST(0) - ST(i) | Вещественное сравнение c модификацией EFLAGS |
FCOMIP FUCOMIP | ST, ST(i) | ST(0) - ST(i); TOPSWR+=1; | Вещественное сравнение c выталкиванием с модификацией EFLAGS |
FXAM | - | Анализ ST(0) |
Команды сравнения сравнивают значение в вершине стека с операндом. По умолчанию (если операнд не задан) происходит сравнение регистров ST(0) и ST(1). В качестве операнда может быть задана ячейка памяти или регистр. Команда устанавливает биты C0, C2, C3 регистра swr в соответствии с таблицей. Сбрасывает в 0 признак C1 при пустом стеке после выполнения команды.
Условие | С3 | С2 | C0 |
ST(0) > src | 0 | 0 | 0 |
ST(0) < src | 0 | 0 | 1 |
ST(0) = src | 1 | 0 | 0 |
Недопустимая операция (#IA) | 1 | 1 | 1 |
Особый интерес представляет команда FCOMI (FUCOMI). Она сравнивает содержимое регистра ST(0) со значением операнда ST(i) и устанавливает биты ZF, PF, CF регистра EFLAGS в соответствии с таблицей. Анализ выполнения сравнения осуществляет последующая команда условного перехода (команда центрального процессора).
Условие | ZF | PF | CF | Переход |
ST(0) > ST(i) | 0 | 0 | 0 | ja |
ST(0) < ST(i) | 0 | 0 | 1 | jb |
ST(0) = ST(i) | 1 | 0 | 0 | je |
ST(0) >= ST(i) | * | 0 | 0 | jae |
ST(0) <= ST(i) | * | 0 | * | jbe |
Недопустимая операция (#IA) | 1 | 1 | 1 |
Команда FXAM проверяет содержимое регистра ST(0) и устанавливает биты C0, C2, C3 регистра swr в соответствии с таблицей. Бит C1 устанавливается равным знаковому биту ST(0).
Класс | С3 | С2 | C0 |
Неподдерживаемый формат | 0 | 0 | 0 |
Нечисло (NaN) | 0 | 0 | 1 |
Конечное число | 0 | 1 | 0 |
Бесконечность | 0 | 1 | 1 |
Ноль | 1 | 0 | 0 |
Пустой регистр | 1 | 0 | 1 |
Ненормированное число | 1 | 1 | 0 |
Команды сравнения данных целого типа
Команда | Операнды | Пояснение | Описание |
FICOM | src | ST(0) - src | Cравнение с целым числом src |
FICOMP | src | ST(0) - src; TOPSWR+=1; | Cравнение с целым числом src с выталкиванием |
FTST | - | ST(0)-0; | Анализ ST(0) (сравнение с нулем) |
Арифметические команды
Команды сопроцессора, входящие в данную группу, реализуют четыре основные арифметические операции — сложение, вычитание, умножение и деление. Имеется также несколько дополнительных команд, предназначенных для повышения эффективности использования основных арифметических команд. С точки зрения типов операндов, арифметические команды сопроцессора можно разделить на команды, работающие с вещественными и целыми числами.
Арифметические команды вещественного типа Схема расположения операндов вещественных команд традиционна для команд сопроцессора. Первый операнд по умолчанию (если не указан в команде) располагается в вершине стека сопроцессора — регистре ST(0), и на его место после выполнения команды записывается результат. Второй операнд может быть расположен либо в памяти, либо в другом регистре стека сопроцессора. По умолчанию в качестве второго операнда используется регистр ST(1). Допустимыми типами операндов в памяти являются вещественные форматы простой и двойной точности. В отличие от целочисленных арифметических команд, вещественные арифметические команды допускают большее разнообразие в сочетании местоположения операндов и самих команд для выполнения конкретного арифметического действия.
Команда | Операнды | Пояснение | Описание |
FADD | dst, src | dst = dst + src; | Сложение вещественное |
FADDP | ST(i), ST(0) | ST(i) = ST(i) + ST(0); TOPSWR+=1; | Сложение вещественное с выталкиванием |
FSUB | dst, src | dst = dst - src; | Вычитание вещественное |
FSUBP | ST(i), ST(0) | ST(i) = ST(i) - ST(0); TOPSWR+=1; | Вычитание вещественное с выталкиванием |
FSUBR | dst, src | dst = src - dst; | Вычитание вещественное реверсивное |
FSUBRP | ST(i), ST(0) | ST(i) = ST(0) - ST(i); TOPSWR+=1; | Вычитание вещественное реверсивное с выталкиванием |
FMUL | dst, src | dst = dst * src; | Умножение вещественное |
FMULP | ST(i), ST(0) | ST(i) = ST(i) * ST(0); TOPSWR+=1; | Умножение вещественное с выталкиванием |
FDIV | dst, src | dst = dst / src; | Деление вещественное |
FDIVP | ST(i), ST(0) | ST(i) = ST(i) / ST(0); TOPSWR+=1; | Деление вещественное с выталкиванием |
FDIVR | dst, src | dst = src /dst; | Деление вещественное реверсивное |
FDIVRP | ST(i), ST(0) | ST(i) = ST(0) / ST(i); TOPSWR+=1; | Деление вещественное реверсивное с выталкиванием |
Арифметические команды целого типа Целочисленные арифметические команды предназначены для работы на тех участках вычислительных алгоритмов, где в качестве исходных данных используются целые числа в памяти, имеющие размерность 4 или 8 байт. Перед выполнением команды целочисленное значение преобразуется к вещественному формату двойной расширенной точности (80 бит).
Команда | Операнды | Пояснение | Описание |
FIADD | src | ST(0) = ST(0) + src; | Сложение целочисленное |
FISUB | src | ST(0) = ST(0) - src; | Вычитание целочисленное |
FISUBR | src | ST(0) = src - ST(0); | Вычитание целочисленное реверсивное |
FIMUL | src | ST(0) = ST(0) * src; | Умножение целочисленное |
FIDIV | src | ST(0) = ST(0) / src; | Деление целочисленное |
FIDIVR | src | ST(0) = src / ST(0); | Деление целочисленное реверсивное |
Дополнительные арифметические команды Команды этой группы не имеют операндов, производят действие с операндом в вершине стека сопроцессора. Результат выполнения операции сохраняется в регистре ST(0). Сбрасывают в 0 признак C1 при пустом стеке, устанавливают в 1 при округлении результата.
Команда | Пояснение | Описание |
FSQRT | ST(0) = √ST(0) | Вычисление квадратного корня |
FABS | ST(0) = |ST(0)| | Вычисление модуля |
FCHS | ST(0) = -ST(0) | Изменение знака |
FXTRACT | temp = ST(0); ST(0)=порядок(temp); TOP-=1; ST(0)=мантисса(temp); | Выделение порядка и мантиссы |
FSCALE | ST(0) = ST(0) · 2ST(1) | Масштабирование по степеням 2 |
FRNDINT | ST(0)=(ST(0)) | Округление ST(0) |
FPREM | ST(0)=ST(0)-Q*ST(1) | Частичный остаток от деления |
FPREM1 |
Команда FXTRACT – выделение порядка и мантиссы. Операнд-источник по умолчанию, хранящийся в регистре ST(0), разделяется на порядок и мантиссу, порядок сохраняется в ST(0), а затем мантисса помещается в стек, меняя при этом указатель вершины стека (поле top). Для операнда, хранящего мантиссу, знак и мантисса остаются неизменными по сравнению с операндом источника. Вместо порядка записывается 3FFFh. После выполнения команды регистр ST(1) хранит значение порядка исходного операнда.
Команда FSCALE– команда масштабирования: изменяет порядок значения, находящегося в вершине стека сопроцессора ST(0) на величину ST(1). Команда не имеет операндов. Величина в ST(1) рассматривается как число со знаком. Его прибавление к полю порядка вещественного числа в ST(0) означает его умножение на величину 2ST(1). С помощью данной команды удобно масштабировать на степень двойки некоторую последовательность чисел в памяти. Для этого достаточно последовательно загружать числа в вершину стека, после чего применять команду FSCALE и сохранять значения обратно в памяти.
Команда FRNDINT – округляет значение, находящееся в вершине стека сопроцессора ST(0). Команда не имеет операндов. Сопроцессор имеет программно-аппаратные средства для выполнения операции округления тех результатов работы команд, которые не могут быть точно представлены. Но операция округления может быть проведена и принудительно к значению в регистре ST(0), для этого предназначена последняя команда в группе дополнительных команд — команда округления. Возможны четыре режима округления величины в ST(0), которые определяются значениями в поле RC управляющего регистра CWR. Для изменения режима округления используются команды FSTCWR и FLDCWR, которые, соответственно, записывают в память содержимое управляющего регистра сопроцессора и восстанавливают его обратно. Таким образом, пока содержимое этого регистра находится в памяти, можно установить необходимое значение поля RC.
Команда FPREM – получение частичного остатка от деления. Исходные значения делимого и делителя размещаются в стеке — делимое в ST(0), делитель в ST(1). Команда производит вычисления по формуле
ST(0)=ST(0)-Q*ST(1),
где Q – целочисленное частное от деления. Делитель рассматривается как некоторый модуль. Поэтому в результате работы команды получается остаток от деления по модулю. Физически работа команды заключается в реализации деление в столбик. При этом каждое промежуточное деление осуществляется отдельной командой FPREM. Цикл, центральное место в котором занимает команда FPREM, завершается, когда очередная полученная разность в ST(0) становится меньше значения модуля в ST(1). Судить об этом можно по состоянию флага С2 в регистре состояния swr:
- если С2=0, то работа команды fprem полностью завершена, так как разность в ST(0) меньше значения модуля в ST(1);
- если С2=1, то необходимо продолжить выполнение команды fprem, так как разность в ST(0) больше значения модуля в ST(1).
Таким образом, необходимо анализировать флаг С2 в теле цикла. Для этого С2 записывается в регистр флагов основного процессора с последующим анализом его командами условного перехода. Другой способ заключается в сравнении ST(0) и ST(1). Команда fprem не соответствует последнему стандарту на вычисления с плавающей точкой IEEE-754. По этой причине в систему команд сопроцессора i387 была введена команда fprem1, которая отличается от FPREM тем, что накладывается дополнительное требование на значение остатка в ST(0). Это значение не должно превышать половины модуля в ST(1). После полного завершения работы команды FPREM/FPREM1 (когда С2=0), биты С0, С3, С1 содержат значения трех младших разрядов частного.
Команды трансцендентных функций
Сопроцессор имеет ряд команд, предназначенных для вычисления значений тригонометрических функций, а также значений логарифмических и показательных функций. Значения аргументов в командах, вычисляющих результат тригонометрических функций, должны задаваться в радианах. Данная группа команд не имеет операндов. Результат сохраняется в регистре ST(0). Сбрасывает в 0 признак C1 при пустом стеке, устанавливают в 1 при округлении. Признак C2 устанавливается в 1 при выходе значения угла за границы диапазона [-263; 263].
Команда | Пояснение | Описание |
FSIN | ST(0) = sin(ST(0)) | Вычисление синуса |
FCOS | ST(0) = cos(ST(0)) | Вычисление косинуса |
FSINCOS | temp=ST(0); ST(0)=sin(temp); TOP-=1; ST(0)=cos(temp); | Вычисление синуса и косинуса |
FPTAN | ST(0)=tg(ST(0)); TOP-=1; ST(0)=1.0; | Вычисление тангенса |
FPATAN | ST(1)=atan(ST(1)/ST(0)); TOP+=1; | Вычисление арктангенса |
F2XM1 | ST(0)=2ST(0)-1; | Вычисление выражения y=2x-1 |
FYL2X | x=ST(0); y=ST(1); TOP+=1; ST(0)=y*log2x; | Вычисление выражения y*log2x |
FYL2XP1 | x=ST(0); y=ST(1); TOP+=1; ST(0)=y*log2(x+1); | Вычисление выражения y*log2(x+1) |
Команда FPTAN – вычисляет частичный тангенс угла: ST(1)=tg(ST(0)), ST(0)=1. Это сделано для совместимости с сопроцессорами 8087 и 287. Выполнение данной команды в них имело следующую особенность: результат команды возвращался в виде двух значений — в регистрах ST(0) и ST(1). Ни одно из этих значений не является истинным значением тангенса. Истинное его значение получается лишь после операции деления ST(0)/ST(1). Таким образом, для получения тангенса требовалась еще команда деления. Синус и косинус в ранних версиях сопроцессоров вычислялись через тангенс половинного угла. В микропроцессоре i387 появились самостоятельные команды для вычисления синуса и косинуса, вследствие чего отпала необходимость составлять соответствующие подпрограммы. Что же до команды fptan, то она по-прежнему выдает два значения в st(0) и st(1), но значение в st(0) всегда равно 1, а в st(1) находится истинное значение тангенса числа, находившегося в st(0) до выполнения команды fptan.
Команда FPATAN вычисляет частичный арктангенс угла: . Команда не имеет операндов. Результат возвращается в регистр ST(1), после чего производится выталкивание вершины стека. Команда FPATAN широко применяется для вычисления значений обратных тригонометрических функций (arcsin, arccos, arcctg, arccosec, arcsec). Для вычисления функции arcsin используется формула:
Для вычисления функции arccos используется формула:
Для вычисления функции arcctg используется формула:
Для вычисления этих функций необходимо выполнить следующую последовательность шагов:
- Если а является мерой угла в градусах, то выполнить ее преобразование в радианную меру.
- Вычислить значение выражения числителя и поместить его в стек.
- Вычислить значение выражения знаменателя и поместить его в стек.
- Выполнить команду fpatan с аргументами в st(0)=знаменатель и st(1)=числитель.
В результате этих действий в регистре ST(0) будет сформировано значение, которое и будет являться значением требуемой функции.
Команда F2XM1 вычисляет значение функции: 2x-1. Исходное значение x размещается в вершине стека сопроцессора ST(0) и должно лежать в диапазоне [-1; 1]. Результат замещает значение в регистре ST(0). Эта команда может быть использована для вычисления показательных функций. 1 вычитается для того, чтобы получить точный результат, когда x близок к нулю. Поскольку нормированное число всегда содержит в качестве первой значащей цифры единицу, если в результате вычисления функции получается число 1,000000000456..., то команда F2XM1, вычитая 1 из этого числа, и затем, нормируя результат, формирует больше значащих цифр, то есть делает его более точным. Неявное вычитание единицы командой F2XM1 компенсируется командой FADD с единичным операндом.
Команда FYL2X вычисляет значение функции ST(0)=ST(1)·log2ST(0). Значение х должно лежать в диапазоне [0;∞). Перед тем, как осуществить запись результата в вершину стека, команда FYL2X выталкивает значения x и у из стека, и только после этого производит запись результата в стек.
Команда FYL2XP1–вычисляет ST(0)=ST(1)·log2(ST(0)+1). Значение х должно лежать в диапазоне [0;∞). Поскольку специальной команды в сопроцессоре для операции возведения в степень нет, возведение в произвольную степень числа с любым основанием производится по формуле:
xy=2y·log2x
Вычисление значения выражения z=y·log2x для любых y>0 и x>0 производится командой сопроцессора FYL2X. Вычисление 2z-1 производится командой F2XM1. Лишнее действие вычитания 1 можно компенсировать сложением с единицей. Но в последнем действии есть тонкий момент, который связан с тем, что величина аргумента x должна лежать в диапазоне: [-1; 1]. В случае, если x превышает это значение (например, для вычисления 163) при вычислении выражения 3·log216 командой FYL2X, получим в стеке значение 12. Попытка вычислить значение 212 командой F2XM1 ни к чему не приведет — результат будет не определен. В этой ситуации используется команда сопроцессора FSCALE, которая вычисляет значение выражения 2х, но для целых значений x со знаком. Применив формулу
2a+b = 2a·2b,
получаем решение проблемы. Разделяем дробный показатель степеней больших 1 по модулю на две части — целую и дробную. После этого вычисляем отдельно командами FSCALE и F2XM1 степени двойки и перемножаем результаты.
Команды управления сопроцессором
Данная группа команд предназначена для общего управления работой сопроцессора. Команды этой группы имеют особенность — перед началом своего выполнения они не проверяют наличие незамаскированных исключений. Однако такая проверка может понадобиться, в частности для того, чтобы при параллельной работе основного процессора и сопроцессора предотвратить разрушение информации, необходимой для корректной обработки исключений, возникших в сопроцессоре. Поэтому некоторые команды управления имеют аналоги, выполняющие те же действия плюс одну дополнительную функцию — проверку наличия исключения в сопроцессоре. Эти команды имеют одинаковые мнемокоды (и машинные коды тоже), отличающиеся только вторым символом N:
- мнемокод, не содержащий второго символа N, обозначает команду, которая перед началом своего выполнения проверяет наличие незамаскированных исключений;
- мнемокод, содержащий второй символ N, обозначает команду, которая перед началом своего выполнения не проверяет наличия незамаскированных исключений, то есть выполняется немедленно, что позволяет сэкономить несколько машинных тактов.
Эти команды имеют одинаковый машинный код. Отличие лишь в том, что перед командами, не содержащими символа N, транслятор ассемблера вставляет команду wait. Команда wait является полноценной командой основного процессора и ее, при необходимости, можно указывать явно. Команда wait имеет аналог среди команд сопроцессора — fwait.
Команда | Операнды | Пояснение | Описание |
FWAIT | - | - | Синхронизация работы с центральным процессором |
FINIT FNINIT | - | CWR=037Fh; SWR=0; TWR=FFFFh; DPR=0; IPR=0; | Инициализация сопроцессора |
FSTSW FNSTSW | dst AX | dst=SWR; AX = SWR; | Считать слово состояния сопроцессора в память |
FSTCW FNSTCW | dst AX | dst=СWR; AX = CWR; | Считать слово управления сопроцессора в память |
FLDCW | src | CWR=src; | Загрузить слово управления сопроцессора |
FCLEX FNCLEX | - | SWR=SWR & 7F00h | Сброс флагов исключений |
FINCSTP | - | TOP+=1; | Увеличение указателя стека сопроцессора на 1 |
FDECSTP | - | TOP-=1; | Уменьшение указателя стека сопроцессора на 1 |
FFREE | ST(i) | TAG(i)=11b | Очистка указанного регистра |
FNOP | - | - | Пустая операция |
FSAVE FNSAVE | dst | ... | Сохранение состояния среды сопроцессора |
FRSTOR | src | ... | Восстановление состояния среды сопроцессора |
FSTENV FNSTENV | dst | ... | Частичное сохранение состояния среды сопроцессора |
FLDENV | src | ... | Восстановление частичного состояния среды сопроцессора |
Команда FWAIT — команда ожидания. Предназначена для синхронизации работы процессора и сопроцессора. Так как основной процессор и сопроцессор работают параллельно, то может создаться ситуация, когда за командой сопроцессора, изменяющей данные в памяти, следует команда основного процессора, которой эти данные требуются. Чтобы синхронизировать работу этих команд, необходимо включить между ними команду wait/fwait. Встретив данную команду в потоке команд, основной процессор приостановит свою работу до тех пор, пока не поступит аппаратный сигнал о завершении очередной команды в сопроцессоре.
Команда FINIT/FNINIT — инициализация сопроцессора. Данная команда инициализирует управляющие регистры сопроцессора определенными значениями: CWR = 037Fh
- RC=00b; округление к ближайшему целому;
- PM,UM,OM,ZM,DM,IM=1; все исключения не замаскированы;
- PC=11b; максимальная точность 64 бита.
SWR = 0h – отсутствие исключений и указание на то, что физический регистр стека сопроцессора r0 является вершиной стека и соответствует логическому регистру ST(0); TWR = FFFFh – все регистры стека сопроцессора пусты; DPR=0; IPR=0. Данную команду используют перед первой командой сопроцессора в программе и в других случаях, когда необходимо привести сопроцессор в начальное состояние.
Команда FSTSW/FNSTSW — сохранение содержимого регистра состояния swr в регистре ах или в ячейке памяти размером 2 байта. Эту команду целесообразно использовать для подготовки к условным переходам по описанной при рассмотрении команд сравнения схеме. Команда FSTCW/FNSTCW — сохранение содержимого регистра управления cwr в ячейке памяти размером 2 байта. Эту команду целесообразно использовать для анализа полей маскирования исключений, управления точностью и округления. В качестве операнда назначения не используется регистр ах, в отличие от команды FSTSW/FNSTSW.
Команда FLDCW — загрузки значения ячейки памяти размером 16 бит в регистр управления cwr. Эта команда выполняет действие, противоположное командам FSTCW/FNSTCW. Команду целесообразно использовать для задания или изменения режима работы сопроцессора. Если в регистре состояния swr установлен любой бит исключения, то попытка загрузки нового содержимого в регистр управления cwr приведет к возбуждению исключения. По этой причине необходимо перед загрузкой регистра cwr сбросить все флаги исключений в регистре swr.
Команда FCLEX/FNCLEX — позволяет сбросить флаги исключений, которые, в частности, необходимы для корректного выполнения команды FLDCW. Ее также применяют и в случаях, когда необходимо сбрасывать флаги исключений в регистре swr, например, в конце подпрограмм обработки исключений. Если этого не делать, то при исполнении первой же команды сопроцессора прерванной программы (кроме тех команд, которые имеют в названии своего мнемокода второй символ n) будет опять возбуждено исключение. PE, UE, OE, ZE, DE, IE, ES, SF и B биты регистра SWR равны 0.
Команда FINCSTP — увеличение указателя стека на единицу (поле top) в регистре swr. Команда не имеет операндов. Действие команды fincstp подобно команде FST, но она извлекает значение операнда из стека "в никуда". Таким образом, эту команду можно использовать для выталкивания, ставшего ненужным операнда, из вершины стека. Команда работает только с полем top и не изменяет соответствующее данному регистру поле в регистре тегов twr, то есть регистр остается занятым и его содержимое из стека не извлекается.
Команда FDECSTP — уменьшение указателя стека (поле top) в регистре swr. Команда не имеет операндов. Действие команды FDECSTP подобно команде FLD, но она не помещает значения операнда в стек. Таким образом, эту команду можно использовать для проталкивания внутрь стека операндов, ранее включенных в него. Команда работает только с полем top и не изменяет соответствующее данному регистру поле в регистре тегов twr, то есть регистр остается пустым.
Команда FFREE —помечает любой регистр стека сопроцессора как пустой. Команда записывает в поле регистра тегов, соответствующего регистру ST(i), значение 11b, что соответствует, пустому регистру. При этом указатель стека (поле tор) в регистре swr и содержимое самого регистра не изменяются. Необходимость в этой команде может возникнуть при попытке записи в регистр ST(i), который помечен, как непустой. В этом случае будет возбуждено исключение. Для предотвращения этого применяется команда FFREE.
Команда FNOP — пустая операция. Не производит никаких действий и влияет только на регистр указателя команды IPR.
Команда FSAVE/FNSAVE — сохранения полного состояния среды сопроцессора в память по адресу, указанному операндом приемник. Размер области памяти зависит от размера операнда сегмента кода use16 или use32:
- use16 — область памяти должна быть 94 байта: 80 байт для восьми регистров из стека сопроцессора и 14 байт для остальных регистров сопроцессора с дополнительной информацией;
- use32 — область памяти должна быть 108 байт: 80 байт для восьми регистров из стека сопроцессора и 28 байт для остальных регистров сопроцессора с дополнительной информацией.
После выполнения сохранения состояния среды сопроцессора производится инициализация сопроцессора.
Команда FRSTOR — используется для восстановления полного состояния среды сопроцессора из области памяти, адрес которой указан операндом источник. Сопроцессор будет работать в новой среде сразу после окончания работы команды frstor.
Команда FSTENV/FNSTENV — сохранение частичного состояния среды сопроцессора в область памяти, адрес которой указан операндом приемник. Размер области памяти зависит от размера операнда сегмента кода usel6 или use32. Формат области частичной среды сопроцессора совпадает с форматом области полной среды, за исключением содержимого стека сопроцессора (80 байт).
Команда FLDENV — восстановление частичного состояния среды сопроцессора содержимым из области памяти, адрес которой указан операндом источник. Информация в данной области памяти была ранее сохранена командой FSTENV/FNSTENV. Команды сохранения среды целесообразно применять в обработчиках исключений, так как только с помощью данных команд можно получить доступ, например, к регистрам DPR и IPR. Не исключено использование этих команд при написании подпрограмм или при переключении контекстов программ в многозадачной среде.
Очень полезный материал. Спасибо. Пытался использовать инструкцию FSCALE для создания функции exp(x). После разделения аргумента на целую и дробную часть при аргументе x=4 (целочисленная часть) функция возвращает 8 (2^3), а не 16 (2^4). Округление не помогает. Пришлось в цикле умножать 2 на 2 4 раза. А так Ваш
совет по использованию F2XM1 только для дробной части выражения x*log 2 e очень помог. Удачи!
Здравствуйте! Хотел предупредить людей, которые будут пользоваться FINCSTP, а потом FDECSTP. Если программировать в SASM, в режиме отладки, чтобы просмотреть значения регистров st0..st7 можно воспользоваться командой отладчика i r f
(Именно так, с пробелом между каждой буквой).
Это первое.
Второе: вышеупомянутые функции надо использовать осторожно. Например, я выкинул из стека число 1 "в никуда". Потом работаю как обычно. Через некоторый кусок кода, я возвращаю единицу при помощи FDECSTP. В результате — ошибка.
Дело в том, что хоть эта единица и выкинулась в st7, но при помощи отладчика можно проследить, что остальные функции могут затереть её.
Вот пример кода:
2
3
4
5
6
7
8
FLDZ
FLD1
FINCSTP ; выкидываем единицу, теперь стек: st0 = 0, st1 = 1, st2 = undefined
; *работа с fpu*
FDECSTP ; !!! в st0 теперь может быть всё что угодно !!!
; …
Уважаемая Елена,а математические функцци : дифференц. урванения,факториалы,лагранжианы,интегралы ,логарифмы, производные,первообразные, множества и тд и тп, весь этот комплекс матема-их вычислений представлен чем: FPU ? или FPU с чем то?
Спасибо заранее, а сайт очень полезный,мне понравился
Часть функций есть в наборе команд сопроцессора (логарифмы, тригонометрия), для вычисления других требуется составление собственных алгоритмов.
Небольшая неточность, думаю: в таблице команд управления для [prog]FSTCW[/prog] операндом указан регистр [prog]AX[/prog], должна быть ячейка памяти. Еще для [prog]FSTSW[/prog] в описании указано "Считать слово состояния сопроцессора в память", точнее будет "в регистр AX"
Дополнение к последнему комментарию. Точнее говоря, приведённая в статье формула для арккосинуса может использоваться при всех значениях аргумента, кроме x=-1. Это ограничение можно обойти, используя команду fpatan с аргументами (1-x)^0,5 и (1+x)^0,5. Однако в любом случае вычисления по этой формуле получаются более сложные (по сравнению с формулой для арксинуса), поэтому применять её на практике вряд ли имеет смысл.
Формулы для вычисления обратных тригонометрических функций лучше убрать, оставить только в качестве примера формулу для арксинуса — она верная и действительно используется при вычислении арксинуса (при этом аргументами команды [prog]fpatan[/prog] выступают [prog]x[/prog] и [prog](1-x^2)^0,5)[/prog].
Остальные формулы верны только для части значений [prog]x[/prog] (при [prog]0<=x<=pi/2[/prog]) и для расчётов соответствующих функций не используются. Так, алгоритм вычисления арккосинуса отличается от арксинуса только тем, что аргументы команды [prog]fpatan[/prog] меняются местами. Для вычисления арккотангенса никаких дополнительных действий не требуется, просто аргументами команды [prog]fpatan[/prog] берутся [prog]1[/prog] и [prog]x[/prog].
Для команды FYL2XP1 на современных процессорах диапазон допустимых значений x>-1, на старых — |x|<1-0,5^0,5 (это примерно 0,293). Однако при x<=-1 исключительная ситуация не генерируется, команда просто возвращает аргумент.
Спасибо за материал! Есть небольшая опечатка в таблице «Команды управления сопроцессором» FINCTSP вместо FINCSTP.
Спасибо, исправила
Это только у меня не отображаются картинки на этой странице?
http://image.prntscr.com/image/e06c54e3d31a4c85ae1c189959898548.png
Исправила, спасибо
Добрый день, у меня вопрос немного странный, но все же, возможно ли с помощью ассемблера(MASM) вызвать команду UEFI BIOS? Спасибо
Затрудняюсь ответить
Ну ладно будем искать, пользуясь случаем хотел поблагодарить вас за сайт, я нашел очень много полезной информации, особенно мне нравится ваш курс по программированию микроконтроллеров(прошел пока 9 уроков). Спасибо
Не команду, а подпрограмму, скорее всего это возможно выполнить находясь в 0 кольце защиты.