2. Система и формат команд сопроцессора
Система команд сопроцессора включает около 80 машинных команд (рис. 5).

Рис. 5. Классификация машинных команд сопроцессора
Мнемоническое обозначение команд сопроцессора характеризует особенности их работы:
Все мнемонические обозначения начинаются с символа F (Float).
Вторая буква мнемонического обозначения определяет тип операнда в памяти, с которым работает команда:
I – целое двоичное число;
В – целое десятичное число;
отсутствие буквы – вещественное число.
Последняя буква Р в мнемоническом обозначении команды означает, что последним действием команды обязательно является извлечение операнда из стека.
При разработке программ для работы с сопроцессором необходимо учитывать следующие факторы:
ограниченность глубины стека сопроцессора;
несовпадение форматов операндов;
отсутствие поддержки на уровне команд сопроцессора некоторых операций, таких как возведение в степень, вычисление тригонометрических функций.
Команды передачи данных
Группа команд передачи данных предназначена для организации обмена между регистрами стека, вершиной стека сопроцессора и ячейками оперативной памяти. Главной функцией всех команд загрузки данных в сопроцессор является преобразование данных к единому представлению в виде вещественного числа расширенного формата. Это же касается и обратной операции – сохранения в памяти данных из сопроцессора.
Команды передачи данных можно разделить на следующие группы:
команды передачи данных в вещественном формате;
команды передачи данных в целочисленном формате;
команды передачи данных в десятичном формате.
К группе команд передачи данных можно отнести также команду обмена вершины регистрового стека ST(0) с любым другим регистром стека сопроцессора ST(i): fxch st(i).
Действие команд загрузки FLD, FILD и FBLD можно сравнить с командой PUSH основного процессора. Аналогично ей (PUSH уменьшает значение в регистре SP) команды загрузки сопроцессора перед сохранением значения в регистровом стеке сопроцессора вычитают из содержимого поля ТОР регистра состояния SWR единицу. Это означает, что вершиной стека становится регистр с физическим номером на единицу меньше. При этом возможно переполнение стека. Так как стек сопроцессора состоит из ограниченного числа регистров, то в него может быть записано максимум восемь значений. Из-за кольцевой организации стека девятое записываемое значение затирает первое. Программа должна иметь возможность обработать такую ситуацию. По этой причине почти все команды, помещающие свой операнд в стек сопроцессора, после уменьшения значения поля ТОР проверяет регистр – кандидат на новую вершину стека – на предмет его занятости. Для анализа этой и подобных ситуаций используется регистр TWR, содержащий слово тегов.
Команды загрузки констант
Основным назначением сопроцессора является поддержка вычислений с плавающей точкой. В математических вычислениях довольно часто встречаются предопределенные константы, и сопроцессор хранит значения некоторых из них. Другая причина использования этих констант заключается в том, что для определения их в памяти (в расширенном формате) требуется 10 байт, а это для хранения, например, единицы расточительно (сама команда загрузки константы, хранящейся в сопроцессоре, занимает два байта). В формате, отличном от расширенного, эти константы хранить не имеет смысла, так как теряется время на их преобразование в тот же расширенный формат. Для каждой предопределенной константы существует специальная команда, которая производит загрузку ее на вершину регистрового стека сопроцессора:
FLDZ — загрузка нуля;
FLD1 — загрузка единицы;
FLDPI — загрузка числа ;
FLDL2T — загрузка двоичного логарифма десяти;
FLDL2E — загрузка двоичного логарифма экспоненты (числа е);
FLDLG2 — загрузка десятичного логарифма двойки;
FLDLN2 — загрузка натурального логарифма двойки.
Команды сравнения данных
Команды сравнения данных сравнивают значение числа в вершине стека и операнда, указанного в команде.
Команды сравнения работают корректно, если операнды в них являются целыми или вещественными числами. Когда один из операндов оказывается нечислом, то фиксируется исключение недействительной ситуации, а коды условия С3...С0 соответствуют исключительной ситуации несравнимых или неупорядоченных операндов. Само же действие сравнения не производится. Процессор предоставляет три команды, позволяющие все же произвести сравнение таких операндов, но как вещественных чисел без учета их порядков:
FUCOM st(i) — команда сравнивает значения (без учета их порядков) в регистрах стека сопроцессора ST(0) и ST(i);
FUCOMP st(i) — команда сравнивает значения (без учета их порядков) в регистрах стека сопроцессора ST(0) и ST(i). Последним действием команды является выталкивание значения из вершины стека;
FUCOMPP st(i) — команда сравнивает значения (без учета их порядков) в регистрах стека сопроцессора ST(0) и ST(i). Последние два действия команды одинаковы — выталкивание значения из вершины стека.
В результате работы команд сравнения в регистре состояния устанавливаются следующие значения битов кода условия С3, С2, С0:
если ST(0) > операнда, то 000;
если ST(0) < операнда, то 001;
если ST(0) = операнду, то 100;
если операнды неупорядочены, то 111.
Арифметические команды
Команды сопроцессора, входящие в группу арифметических команд, реализуют четыре основные арифметические операции – сложение, вычитание, умножение и деление. Имеется также несколько дополнительных команд, предназначенных для повышения эффективности использования основных арифметических команд. С точки зрения типов операндов арифметические команды сопроцессора можно разделить на команды, работающие с вещественными и целыми числами.
Целочисленные арифметические команды
Целочисленные арифметические команды предназначены для работы на тех участках вычислительных алгоритмов, где в качестве исходных данных используются целые числа в памяти в формате слово и короткое слово, имеющие размерность 16 и 32 бита.
Для команд, реализующих арифметические действия деления и вычитания, важен порядок расположения операндов. По этой причине система команд сопроцессора содержит соответствующие реверсивные команды, повышающие удобство программирования вычислительных алгоритмов. Чтобы отличить эти команды от обычных команд деления и вычитания, их мнемокоды оканчиваются символом R.
Вещественные арифметические команды
Схема расположения операндов вещественных команд традиционна для команд сопроцессора. Один из операндов располагается в вершине стека сопроцессора – регистре ST(0), куда после выполнения команды записывается и результат, а второй операнд может быть расположен либо в памяти, либо в другом регистре стека сопроцессора. Допустимыми типами операндов в памяти являются все перечисленные ранее вещественные форматы за исключением расширенного.
Команды трансцендентных функций
Сопроцессор имеет ряд команд, предназначенных для вычисления значений тригонометрических функций, таких как синус, косинус, тангенс, арктангенс, а также значений логарифмических и показательных функций.
Значения аргументов в командах, вычисляющих результат тригонометрических функций, должны задаваться в радианах. Для нахождения радианной меры угла по его градусной мере необходимо число градусов умножить на /180 (=0,017453), число минут – на /(180 • 60) (=0,000291), а число секунд – на /(180 • 60 • 60) (=0,000005) и найденные произведения сложить.
Впервые трансцендентные команды появились в сопроцессоре i387 как самостоятельные команды для вычисления синуса и косинуса, вследствие чего отпала необходимость составлять соответствующие подпрограммы.
Команды управления
Последняя группа команд предназначена для общего управления работой сопроцессора. Команды этой группы имеют особенность – перед началом своего выполнения они не проверяют наличие незамаскированных исключений.
В группе команд управления можно выделить подгруппу команд, работающих с так называемой средой сопроцессора. Среда сопроцессора — это совокупность регистров сопроцессора и их значений.
Общие рекомендации по написанию программ для сопроцессора.
1. Первый фрагмент программы с командами сопроцессора должен начинаться с команды FINIT. Если программа содержит несколько независимых друг от друга фрагментов с командами сопроцессора, каждый такой фрагмент должен начинаться с команды FINIT.
2. При написании программы необходимо учитывать то, что процессор и сопроцессор работают параллельно. То есть необходимо особенно тщательно программировать участки, на которых планируется параллельное выполнение команд обоих процессоров. Особое внимание нужно обращать на синхронизацию общих операндов и обработку возможных исключительных ситуаций.
3. Рекомендуется обработку исключений доверять самому сопроцессору, кроме исключения недействительной операции, что позволит своевременно обнаружить ошибки алгоритма.
4. При написании программ следует установить такой режим округления, который позволит получить максимально точный результат.
5. Для повышения производительности процессора при передаче данных необходимо использовать директиву EVEN. Ее действие заключается в том, что данные, описываемые следующей за ней одной из директив резервирования и инициализации данных, размещаются по ближайшему адресу, значение которого кратно 2. Так как все типы данных сопроцессора имеют длину, кратную двум, то желательно все ячейки памяти, содержащие значения для обработки сопроцессором, размещать в сегменте данных одним блоком, предваряя их описание директивой EVEN.
Форматы данных
Сопроцессор расширяет номенклатуру форматов данных, с которыми работает основной процессор. Форматы данных, с которыми работает сопроцессор:
двоичные целые числа в трех форматах – 16, 32 и 64 бита (табл. 1);
упакованные целые десятичные (BCD) числа – длина максимального числа составляет 18 упакованных десятичных цифр (9 байтов);
вещественные числа в трех форматах – коротком (32 бита), длинном (64 бита), расширенном (80 битов).
Кроме этих основных форматов, сопроцессор поддерживает специальные численные значения, к которым относятся:
денормализованные вещественные числа – это числа, меньшие минимального нормализованного числа для каждого вещественного формата, поддерживаемого сопроцессором;
нуль;
положительные и отрицательные значения бесконечности;
нечисла;
неопределенности и неподдерживаемые форматы.
Таблица 1
Форматы целых чисел сопроцессора
|
Формат |
Размер, битов |
Диапазон значений |
|
Целое слово |
16 |
- 32 768…+ 32 767 |
|
Короткое слово |
32 |
-2 109 … +2 109 |
|
Длинное слово |
64 |
-9 1018 … +9 1018 |
Упакованные целые десятичные числа.
Сопроцессор поддерживает один формат упакованных целых десятичных чисел, или BCD-чисел (рис. 6).

Рис. 6. Формат десятичного числа сопроцессора
Упакованные десятичные числа также представляются в стеке сопроцессора в расширенном формате. Упакованные десятичные числа в программе описываются директивой DТ. Например, целое число 5 365 904 в формате упакованного десятичного числа может быть описано следующим образом:
ch_dt dt 5365904
;представление в памяти: ch_dt=04 59 36 05 00 00 00 00 00 00
В сопроцессоре имеются всего две команды для работы с упакованными десятичными числами — это команды сохранения и загрузки.
Вещественные числа
Основной тип данных, с которыми работает сопроцессор, — вещественный. Данные этого типа описываются тремя форматами: коротким, длинным и расширенным (рис. 7).

Рис. 7. Форматы вещественных чисел сопроцессора
Для представления вещественного числа используется следующая формула:
![]()
где М — мантисса числа А (мантисса должна удовлетворять условию |М| < 1); N – основание системы счисления, представленное целым положительным числом; р – порядок числа, показывающий истинное положение точки в разрядах мантиссы (по этой причине вещественные числа имеют еще название чисел с плавающей точкой, так как ее положение в разрядах мантиссы зависит от значения порядка).
Для удобства обработки в процессоре IA-32 чисел с плавающей точкой его архитектурой накладываются некоторые ограничения на компоненты формулы:
основание системы счисления N = 2;
мантисса М должна быть представлена в нормализованном виде. Нормализация может отличаться для разных типов процессоров. Для архитектуры сопроцессора IA-32 нормализованным является число вида:
,
где s — значение знакового разряда (0 — число больше нуля, 1 - число меньше нуля); q — порядок числа, его назначение аналогично назначению порядка р.
В этой формуле знак имеют и порядок вещественного числа, и его мантисса. На рис. 6 видно, что формат хранения вещественного числа в памяти имеет только поле для знака мантиссы. А где же хранится знак порядка?
В сопроцессоре Intel на аппаратном уровне принято соглашение, что порядок р определяется в формате вещественного числа особым значением q, называемым характеристикой. Величина q связана с порядком р посредством следующей формулы и представляет собой некоторую константу, условно называемой смещением:
q = р + фиксированное смещение.
Для каждого из трех возможных форматов вещественных чисел смещение q имеет разное, но фиксированное для конкретного формата значение, которое зависит от количества разрядов, отводимых под характеристику (табл. 2).
Таблица 2
Форматы вещественных чисел
|
Формат |
Короткий |
Длинный |
Расширенный |
|
Длина числа (биты) |
32 |
64 |
80 |
|
Размерность мантиссы М |
24 |
53 |
64 |
|
Диапазон значений |
10-38 … 10+38 |
10-308 … 10+308 |
10-4932 … 10+4932 |
|
Размерность характеристики q |
8 |
11 |
15 |
|
Значение фиксированного смещения |
+127 |
+1023 |
+16 383 |
|
Диапазон характеристик q |
0…255 |
0…2047 |
0…32 767 |
|
Диапазон порядков р |
-126 … +127 |
-1022 … +1023 |
-16 382 … +16 383 |
В таблице показаны диапазоны значений характеристик q и соответствующих им истинных порядков р вещественных чисел. При этом нулевому порядку вещественного числа в коротком формате соответствует значение характеристики равное 127,которому в двоичном представлении соответствует значение 01 11 11 11. Отрицательному порядку р, например -1, будет соответствовать характеристика q=-1+127= 126, или в двоичном виде — 01 11 11 10. Положительному порядку например +1, будет соответствовать характеристика q = 1 + 127 = 128, или в двоичном виде – 10 00 00 00. То есть все положительные порядки имеют в двоичном представлении характеристики старший бит равный единице, а отрицательные порядки - нет. Таким образом, знак порядка «спрятан» в старшем бите характеристики.
Короткое вещественное число длиной в 32 разряда определяется директивой DD. При том обязательным в записи числа является наличие десятичной точки, даже если оно не имеет дробной части. Для транслятора десятичная точка является и указанием, что число нужно представить в виде числа с плавающей точкой в коротком формате. Это же касается длинного и расширенного форматов представления вещественных чисел, определяемых директивами DQ и DT. Другой способ задания вещественного числа директивами DD, DQ, DT — экспоненциальная форма с использованием символа «е».
Например, вещественное число 45,56 в программе в коротком формате может быть задано тремя способами:
dd 45.56
dd 45.56e0
dd 0.4556e2.
В памяти это число будет выглядеть так: 71 3d 36 42.
Учитывая, что в архитектуре Intel принят «перевернутый» порядок следования байтов в памяти в соответствии с принципом «младший байт по младшему адресу», истинное представление числа 45,56 будет следующим: 42 36 3d 71. Двоичное представление в памяти числа 45,56 показано на рис. 8.

Рис. 8. Двоичное представление в памяти вещественного числа в директиве DD
Из рисунка видно, что старшая единица мантиссы при представлении в памяти отсутствует.
В расширенном формате вещественное число 45,56 выглядит следующим образом:
dt 45.56
В памяти это число будет выглядеть так: 71 3d 0a d7 a3 70 3d b6 04 40.
Перевернув его, получим истинное значение в памяти:
04 40 b6 3d 70 a3 d7 0a 3d 71.
Двоичное представление числа 45,56 (рис. 9).

Рис. 9. Двоичное представление числа в расширенном формате
