Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Аппаратное обеспечение IBM PC

© Александр Фролов, Григорий Фролов
Том 2, книга 1, М.: Диалог-МИФИ, 1992.

[Назад] [Содеожание] [Дальше]

12.4. Система команд сопроцессора

Возможны три формата команд сопроцессора, аналогичные форматам команд центральных процессоров 8086/80286/80386. Это команды с обращением к оперативной памяти, команды с обращением к одному из численных регистров и команды без операндов, заданных явным образом.

Команды с обращением к памяти могут занимать от двух до четырех байтов, в зависимости от способа адресации операнда, находящегося в памяти:

¦1 байт    ¦1 байт      ¦1 байт     ¦1 байт     ¦
+-----T----+---T----T---+-----------+-----------+
¦11011¦КОП1¦MOD¦КОП2¦R/M¦ Смещение1 ¦ Смещение2 ¦
L-----+----+---+----+---+-----------+------------



Первые пять битов соответствуют команде центрального процессора ESC. Поля КОП1 и КОП2 определяют выполняемую команду, т.е. содержат код операции. Поля MOD и R/M вместе с полями "Смещение1" и "Смещение2" задают адрес операнда в памяти аналогично тому, как это происходит в процессорах 8086/80286/80386. Однако есть и отличия, связанные с возможностью адресации численных регистров сопроцессора.

Приведем таблицу, показывающую зависимость способа адресации от содержимого полей MOD и R/M:

-----T----------------------------------------------¬
¦Поле¦                       Поле MOD               ¦
¦R/M +---------T---------------T----------------T---+
¦    ¦    00   ¦       01      ¦    10          ¦11 ¦
+----+---------+---------------+----------------+---+
¦000 ¦(bx)+(si)¦(bx)+(si)+disp8¦(bx)+(si)+disp16¦ST0¦
¦001 ¦(bx)+(di)¦(bx)+(di)+disp8¦(bx)+(di)+disp16¦ST1¦
¦010 ¦(bp)+(si)¦(bp)+(si)+disp8¦(bp)+(si)+disp16¦ST2¦
¦011 ¦(bp)+(di)¦(bp)+(di)+disp8¦(bp)+(di)+disp16¦ST3¦
¦100 ¦   (si)  ¦   (si)+disp8  ¦   (si)+disp16  ¦ST4¦
¦101 ¦   (di)  ¦   (di)+disp8  ¦   (di)+disp16  ¦ST5¦
¦110 ¦  disp16 ¦   (bp)+disp8  ¦   (bp)+disp16  ¦ST6¦
¦111 ¦   (bx)  ¦   (bx)+disp8  ¦   (bx)+disp16  ¦ST7¦
L----+---------+---------------+----------------+----


Если в таблице указаны значения смещения disp8 или disp16, это означает, что в команде присуствует один или два байта смещения, соответственно.

Если поле MOD содержит значение 11, возможна адресация численных регистров ST0...ST1. При этом команда не содержит байтов смещения.

Формат команды с обращением к численному регистру приведен на следующем рисунке:

¦1 байт    ¦1 байт      ¦
+-----T----+---T----T---+
¦11011¦КОП1¦11 ¦КОП2¦STi¦
L-----+----+---+----+----


Видно, что это есть частный случай предыдущей команды, в которой поле MOD содержит значение 11 и отсутствуют байты смещения.

Самый простой формат имеют команды без явного обращения к операндам:

¦1 байт    ¦1 байт      ¦
+-----T----+---T--------+
¦11011¦КОП1¦11 ¦   КОП2 ¦
L-----+----+---+---------


Разумеется, если вы пишете программу для сопроцессора на языке ассемблера, вы можете использовать мнемоническое обозначение команд. Все мнемоники команд сопроцесора начинаются с буквы F, поэтому их легко отличить от команд процессоров 8086/80286/80386/80486.

Все команды сопроцессора можно разделить на несколько групп:

  • команды пересылки данных;
  • арифметические команды;
  • команды сравнений чисел;
  • трансцендентные команды;
  • управляющие команды.

Команды пересылки данных предназначены для загрузки чисел из оперативной памяти в численные регитры, записи данных из численных регистров в операивную память, копирования данных из одного численного регистра в другой.

Арифметические команды выполняют такие операции, как сложение, вычитание, умножение, деление, извлечение квадратного корня, нахождение частичного остатка, округление и т.п.

Команды сравнения сравнивают вещественные и целые числа, выполняют анализ чисел.

Трансцендентные команды предназначены для вычисления различных тригонометрических, логорифмических, показательных и гиперболических функций - sin(), cos(), tg() и т.п.

Последняя группа команд - управляющие команды - обеспечивают установку режима работы арифметического сопроцессора, его сброс и инициализацию, перевод сопроцессора в защищенный режим работы и т.д.

Следующие разделы будут посвящены детальному описанию различных групп команд сопроцессора.

12.4.1. Команды пересылки данных

Запись в стек

FLD     ST(0) <- память, вещественный формат
FILD    ST(0) <- память, целый формат
FBLD    ST(0) <- память, десятичный формат


Команды FLD, FILD, FBLD загружают в вершину стека вещественное, целое и десятичное числа, соответственно.

При выполнении этих команд операнд считывается из оперативной памяти, преобразуется в формат с расширенной точностью. Затем поле ST регистра состояния уменьшается на единицу и выполняется запись операнда в численный регистр, определяемый новым значением поля ST. Т.е. операнд записывается в стек численных регистров, а указатель стека - поле ST - уменьшается на единицу. По своему действию эти команды напоминают команду PUSH центрального процессора.

Непосредственно перед загрузкой численного регистра проверяется содержимое поля TAG0. Если это содержимое не равно 11 (пустой регистр), в регистре состояния устанавливается флаг IE (недействительная операция) и вырабатывается прерывание (если в регистре управления не установлена маска IM - маска недействительной операции).

Извлечение из стека

FSTP    память -> ST(0), вещественный формат
FISTP   память -> ST(0), целый формат
FBSTP   память -> ST(0), десятичный формат


Команды извлечения чисел из стека выполняют действие, обратное только что описанному. Содержимое численного регистра, номер которого определяется полем ST регистра состояния, преобразуется в необходимый формат и записывается в ячейки оперативной памяти, заданные операндом команды.

После записи содержимое поля ST увеличивается на единицу. Эти действия аналогичны выполняемым командой POP центрального процессора.

В зависимости от команды (FSTP, FISTP или FBSTP) производится преобразование формата (из расширенного в вещественный, целый или десятичный, соответственно). В процессе преобразования для команд FSTP и FISTP выполняется округление в соответствии с содержимым поля RC регистра управления. Для команды FBSTP округление всегда выполняется следующим образом - прибавляется число 0.5, затем дробная часть результата отбрасывается.

Копирование данных

FST     память -> ST(0), вещественный формат
FIST    память -> ST(0), целый формат
FBST    память -> ST(0), десятичный формат
        (только 80387, 80486)


Эти команды пересылают данные из верхушки стека в область памяти, указанную операндом команды. При этом содержимое указателя стека (поля ST) не изменяется.

Команда FST в качестве операнда может использовать ссылку на численный регистр ST(i), поэтому вы можете использовать эту команду для копирования верхушки стека в любой другой численный регистр.

При записи данных в оперативную память выполняется преобразование формата (в вещественный для FST, в целый для FIST и в десятичный для FBST.

Для сопроцессора 80286 вместо отсутствующей команды FBST можно выполнить следующие две команды, которые приведут к такому же результату:

FLD          ST(0)
FBSTP   dec_number


Обмен

FXCH    ST(i) -> ST(0), ST(0) -> ST(i)


Команда выполняет обмен содержимым верхушки стека ST(0) и численного регистра, указанного в качестве операнда команды.

Загрузка констант

FLDZ    0 -> ST(0) - Загрузить нуль
FLD1    1 -> ST(0) - Загрузить единицу
FLDPI   "Пи" -> ST(0) - Загрузить число "пи".
FLDLG2  log102 -> ST(0) - Загрузить log102 
FLDLN2  loge2 -> ST(0) - Загрузить loge2 
FLDL2T  loge10 -> ST(0) - Загрузить loge10 
FLDL2E  log2e -> ST(0) - Загрузить log2e 


Гораздо быстрее загружать константы с помощью специальных команд, чем использовать команды загрузки данных из оперативной памяти.

12.4.2. Арифметические команды

Сопроцессор использует шесть основных типов арифметических команд:

Fxxx Первый операнд берется из верхушки стека (источник), второй - следующий элемент стека. Результат выполнения команды записывается в стек.
Fxxx память Источник берется из памяти, приемником является верхушка стека ST(0). Указатель стека ST не изменяется, команда действительна только для операндов с одинарной и двойной точностью.
Fixxx память Аналогично предыдущему типу команды, но операндами могут быть 16- или32-битовые целые числа.
Fxxx ST, ST(i) Для этого типа регистр ST(i) является источником, а ST(0) - верхушка стека - приемником. Указатель стека не изменяется.
Fxxx ST(i), ST Для этого типа регитр ST(0) является источником, а ST(i) - приемником. Указатель стека не изменяется.
FxxxP ST(i), ST Регистр ST(i) - приемник, регистр ST(0) - источник. После выполнения команды источник ST(0) извлекается из стека.

Строка "xxx" может принимать следующие значения:

ADD     Сложение

SUB     Вычитание

SUBR    Обратное вычитание, уменьшаемое и вычитаемое
        меняются местами

MUL     Умножение

DIV     Деление

DIVR    Обратное деление, делимое и делитель меняются
        местами


Кроме основных арифметических команд имеются дополнительные арифметические команды:

FSQRT Извлечение квадратного корня
FSCALE Масштабирование на степень числа 2
FPREM Вычисление частичного остатка
FRNDINT Округление до целого
FXTRACT Выделение порядка числа и мантиссы
FABS Вычисление абсолютной величины числа
FCHS Изменение знака числа

По команде FSQRT вычисленное значение квадратного корня записывается в верхушку стека ST(0).

Команда FSCALE изменяет порядок числа, находящегося в ST(0). По этой команде значение порядка числа ST(0) складывается с масштабным коэффициентом, который должен быть предварительно записан в ST(1). Действие этой команды можно представить следующей формулой:

ST(0) = ST(0) * 2n, где -215 <= n <= +215


В этой формуле n - это ST(1).

Команда FPREM вычисляет остаток от деления делимого ST(0) на делитель ST(1). Знак результата равен знаку ST(0), а сам результат получается в вершине стека ST(0).

Действие команды заключается в сдвигах и вычитания, аналогично "ручному" делению "в столбик". После выполнения команды флаг C2 регистра состояния может принимать следующие значения:

 остаток от деления, полученный в ST(0), меньше делителя ST(1), команда завершилась полностью;
ST(0) содержит частичный остаток, программа должна еще раз выполнить команду для получения точного значения остатка.

Команда RNDINT округляет ST(0) в соответствии с содержимым поля RC управляющего регистра.

Команда FABS вычисляет абсолютное значение ST(0). Аналогично, команда FCHS изменяет знак ST(0) на противоположный.

12.4.3. Команды сравнений чисел

В процессорах 8086/80286/80386 команды условных переходов выполняются в соответствии с установкой отдельных битов регистра флагов процессора. В арифметическом сопроцессоре существуют специальные команды сравнений, по результатам выполнения которых устанавливаются биты кодов условий в регистре состояния:

FCOM Сравнение
FICOM Целочисленное сравнение
FCOMP Сравнение и извлечение из стека
FICOMP Целочисленное сравнение и извлечение из стека
FCOMPP Сравнение и двойное извлечение из стека
FTST Сравнение операнда с нулем
FXAM Анализ операнда

Команда FCOM вычитает содержимое операнда, размещенного в оперативной памяти, из верхушки стека ST(0). Результат вычитания никуда не записывается и указатель верхушки стека ST не изменяется.

Обозначим операнд команды сравнения как "x". В следующей таблице приведем значения битов кодов условия после выполнения команды "FCOM x":

C3 C0 Условие
0 0 ST(0) > x
0 1 ST(0) < x
1 0 ST(0) = x
1 1 ST(0) и x не сравнимы.

Последняя комбинация возникает при попытке сравнения нечисел, неопределенностей или бесконечностей, а также в некоторых других случаях.

Команда FICOM работает с 16- или 32-битовыми числами, в остальном она аналогична команде FCOM.

Команды FCOMP и FICOMP аналогичны, соответственно, командам FCOM и FICOM, за исключением того, что после выполнения операнд извлекается из стека.

Команда FCOMPP выполняет те же действия, что и FCOM, но она после выполнения извлекает из стека оба операнда, участвовавших в сравнении.

Для сравнения операнда с нулем предназначена команда FTST. После ее выполнения коды условий устанавливаются в соответствии со следующей таблицей:

C3 C0 Условие
0 0 ST(0) > 0
0 1 ST(0) < 0
1 0 ST(0) = 0
1 1 ST(0) и 0 не сравнимы.

Команда FXAM анализирует содержимое ST(0). После ее выполнения устанавливаются коды условий, по которым можно судить о знаке числа, о его конечности или бесконечности, нормализованности и т.д.

Бит C1 содержит знак анализируемого числа:

C1 Знак числа
0 положительное число;
1 отрицательное число.

С помощью бита C0 можно определить, является число конечным или бесконечным:

C0 Конечность/бесконечность числа
0 конечное число;
1 бесконечное число.

Для конечных чисел дальнейшая классификация может проводиться по содержимому кодов условий C2 и C3:

C3 C2 Описание числа
0 0 Ненормализованное число
0 1 Нормализованное число
1 0 Нулевое число
1 1 Число денормализовано

Аналогично, для бесконечных чисел коды условий C2 и C3 имеют следующее значение:

C3 C2 Описание числа
0 0 Нечисло
0 1 Бесконечное число
1 0 Пустое число
1 1 Пустое число

С помощью команды "FSTSW AX" программа может переписать содержимое регистра состояния сопроцессора в регистр AX центрального процессора. Далее содержимое регистра AH можно переписать в регистр флагов центрального процессора при помощи команды SAHF. Биты кодов условий сопроцессора отображаются на регистр флагов центрального процессора таким образом, что для анализа кодов условий можно использовать команды условных переходов:

---T-T-T-T-T-T-T--¬
¦B ¦C3¦  ¦ST¦  ¦C2¦C1¦C0¦
L--+--+--+--+--+--+--+---

---T-T-T-T-T-T-T--¬
¦SF¦ZF¦  ¦AF¦  ¦PF¦  ¦CF¦
L--+--+--+--+--+--+--+---



Например, в следующем фрагменте программы выполняется переход к метке error, если операнды несравнимы:

fcom
fstsw   ax
sahf
je              error


12.4.4. Трансцендентные команды

Трансцендентные команды предназначены для вычисления таких функций, как тригонометрические (sin, cos, tg,...), обратные тригонометрические (arcsin, arccos,...), показательные (xy, 2x, 10x, ex), гиперболические (sh, ch, th,...), обратные гиперболические (arsh, arch, arcth,...).

В следующей таблице приведены все трансцендентные команды сопроцессора:

FPTAN Вычисление частичного тангенса
FPATAN Вычисление частичного арктангенса
FYL2X Вычисление y*log2(x)
FYL2XP1 Вычисление y*log2(x+1)
F2XM1 Вычисление 2x-1
FCOS Вычисление cos(x) (только 80387/80486)
FSIN Вычисление sin(x) (только 80387/80486)
FSINCOS Вычисление sin(x) и cos(x) одновременно (только 80387/80486)

Команда FPTAN вычисляет частичный тангенс ST(0), размещая в стеке такие два числа x и y, что y/x = tg(ST(0)).

После выполнения команды число y располагается в ST(0), а число x включается в стек сверху (т.е. записывается в ST(1)). Аргумент команды FPTAN должен находится в пределах:

0 <= ST(0) <= pi/4

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

sin(z) = 2*(y/x) / (1 + (y/x)2)
cos(z) = (1 - (y/x)2) / (1 + (y/x)2)
tg(z/2) = y/x;
ctg(z/2) = x/y;
cosec(z) =  (1 + (y/x)2) / 2*(y/x)
sec(z) = (1 + (y/x)2) / (1 - (y/x)2)


В этой таблице z - значение, находившееся в ST(0) до выполнения команды FPTAN, x и y - значения в регистрах ST(0) и ST(1), соответственно.

Команда FPATAN вычисляет частичный арктангенс z=arctg(ST(0)/ST(1))=arctg(x/y).


Перед выполнением команды числа x и y располагаются в ST(0) и ST(1), сответственно. Аргументы команды FPATAN должен находится в пределах:

0 < y < x


Результат записывается в ST(0).

Команда FYL2X вычисляет выражение y*log2(x), операнды x и y размещаются, соответственно, в ST(0) и ST(1). Операнды извлекаются из стека, а результат записывается в стек. параметр x должен быть положительным числом.

Пользуясь результатом выполнения этой команды, можно вычислить следующим образом логарифмические функции:

log2(x) = FYL2(x)
loge(x) = loge(2) * log2(x) = FYL2X(loge(2), x) =
                = FYL2X(FLDLN2, x)
log2(x) = log10(2) * log2(x) = FYL2X (log10(2), x) =
                = FYL2X(FLDLG2, x)


Функция FYL2XP1 вычисляет выражение y*log2(x+1), где x соответствует ST(0), а y - ST(1). Результат записывается в ST(0), оба операнда выталкиваются из стека и теряются.

На операнд x накладывается ограничение:

0 < x < 1 - 1/sqrt(2)


Команда F2XM1 вычисляет выражение 2x-1, где x - ST(0). Результат записывается в ST(0), параметр должен находится в следующих пределах:

0 <= x <= 0,5


Команда FCOS вычисляет cos(x) (только для 80387/80486). Параметр x должен находится в ST(0), туда же записывается результат выполнения команды.

Команда FSIN аналогична команде FCOS, но вычисляет значение косинуса ST(0).

Команда FSINCOS вычисляет одновременно значения синуса и косинуса параметра ST(0). Значение синуса записывается в ST(1), косинуса - в ST(0).

На этом мы закончим описание трансцендентных команд сопроцессора и перейдем к управляющим командам.

12.4.5. Управляющие команды

Управляющие команды предназначены для работы с нечисловыми регистрами сопроцессора. Некоторые команды имеют альтернативные варианты. Мнемоники этих команд могут начинаться с FN или с F. Первый вариант соответствует командам "без ожидания". Для команд "без ожидания" процессор не проверяет, занят ли сопроцессор выполнением команды, т.е. бит занятости B не проверяется. Численные особые случаи также игнорируются.

Варианты команд "с ожиданием" действуют также, как и обычные команды сопроцессора.

Приведем таблицу управляющих команд сопроцессора:

FNSTCW (FSTCW)          Записать управляющее слово
FLDCW                   Загрузить управляющее слово
FNSTSW (FSTSW)          Записать слово состояния
FNSTSW AX (FSTSW AX)    Записать слово состояния в AX,
                        не поддерживается сопроцессором 8087
FNCLEX (FCLEX)          Сбросить особые случаи
FNINIT (FINIT)          Инициализировать сопроцессор
FNSTENV (FSTENV)        Записать среду
FLDENV                  Загрузить среду
FNSAVE (FSAVE)          Записать полное состояние
FRSTOR                  Восстановить полное состояние
FINCSTP                 Увеличить указатель стека на 1
FDECSTP                 Уменьшить указатель стека на 1
FFREE                   Освободить регистр
FNOP                    Холостая команда, нет операции
FSETPM                  Установить защищенный режим работы


Команда FNSTCW записывает содержимое управляющего регистра в оперативную память.

Команда FLDCW загружает управляющий регистр данными из оперативной памяти и обычно используется для изменения режима работы сопроцессора.

Команда FNSTSW записывает содержимое регистра состояния в оперативную память. Команда FNSTSW AX записывает содержимое этого регистра в регистр AX центрального процессора для его последующего анализа командами условных переходов.

Сопроцессор 8087 не имеет варианта команды FSTSW AX, поэтому приходится вначале записывать регистр состояния в память, а затем в регистр флагов процессора 8086.

Команда FNCLEX сбрасывает флаги особых случаев в регистре состояния сопроцессора. Кроме того, сбрасываются биты ES и B.

Команда FNINIT инициализирует регистр состояния, управляющий регистр и регистр тегов в соответствии со следующей таблицей:

Регистр         Устанавливаемый режим работы


Управляющий     Проективная бесконечность,
                        округление к ближайшему,
                        расширенная точность,
                        все особые случаи замаскированы.

Состояния       B=0 (бит занятости сброшен),
                        код условия не определен,
                        ST=ES=0,
                        флаги особых случаев установлены в нуль.

Тегов           Все поля регистра тегов содержат значение
                        11 (пустой регистр).


Команда FNSTENV записывает в память содержимое всех регистров, кроме численных, в следующем формате:

------------------------¬
¦  Управляющий регистр  ¦
+-----------------------+
¦   Регистр состояния   ¦
+-----------------------+
¦      Регистр тегов    ¦
+-----------------------+
¦                       ¦
+-  Указатель команды  -+
¦                       ¦
+-----------------------+
¦                       ¦
+- Указатель операнда  -+
¦                       ¦
L------------------------


Команда FLDENV предназначена для загрузки регистров, сохраненных ранее командой FNSTENV. Обе эти команды полезны в программах обработки особых случаев.

Команды FNSAVE и FRSTOR действуют аналогично командам FNSTENV и FLDENV, но они дополнительно сохраняют и восстанавливают содержимое численных регистров. Формат области сохранения регистров, занимающей 94 байта, приведен на следующем рисунке:

------------------------¬
¦  Управляющий регистр  ¦
+-----------------------+
¦   Регистр состояния   ¦
+-----------------------+
¦      Регистр тегов    ¦
+-----------------------+
¦                       ¦
+-  Указатель команды  -+
¦                       ¦
+-----------------------+
¦                       ¦
+- Указатель операнда  -+
¦                       ¦
+-----------------------+-------------------------------¬
¦                          ST(0)                        ¦
+-------------------------------------------------------+
¦                          ST(1)                        ¦
+-------------------------------------------------------+
¦                          ST(2)                        ¦
+-------------------------------------------------------+
¦                          ST(3)                        ¦
+-------------------------------------------------------+
¦                          ST(4)                        ¦
+-------------------------------------------------------+
¦                          ST(5)                        ¦
+-------------------------------------------------------+
¦                          ST(6)                        ¦
+-------------------------------------------------------+
¦                          ST(7)                        ¦
L--------------------------------------------------------



Команды FINCSTP и FDECSTP, соответственно, увеличивают и уменьшают на 1 указатель стека SP.

Команда FFREE ST(i) помечает численный регистр ST(i) как пустой, записывая в соответствующее поле регистра тегов значение 11.

Команда FNOP не производит никаких действий.

Команда FSETPM переводит сопроцессор в защищенный режим работы. Подробное рассмотрение защищенного режима работы выходит за рамки данной книги.

[Назад] [Содеожание] [Дальше]