что такое арифметический сопроцессор

Что такое арифметический сопроцессор

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

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

Рис. 10.15. Формат команд с обращением к памяти

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

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

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

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

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

Рис. 10.16. Формат команд с обращением к численному регистру

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

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

Рис. 10.17. Формат команд без явного обращения к операндам

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

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

· команды пересылки данных;

· команды сравнений чисел;

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

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

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

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

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

Приведем описание команд, предназначенных для пересылки данных.

Запись в стек

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

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

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

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

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

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

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

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

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

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

Обмен

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

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

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

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

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

Источник берется из памяти, приемником является верхушка стека ST(0). Указатель стека ST не изменяется, команда действительна только для операндов с одинарной и двойной точностью

Аналогично предыдущему типу команды, но операндами могут быть 16- или 32-разрядные целые числа

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

Источник

Математический сопроцессор

С появлением новых моделей микропроцессоров Intel совершенствовались и сопроцессоры, хотя их программная модель осталась практически неизменной. Как отдельные (а, соответственно, необязательные в конкретной комплектации компьютера) устройства, сопроцессоры сохранялись вплоть до модели микропроцессора i386 и имели название i287 и i387 соответственно. Начиная с модели i486, сопроцессор исполняется в одном корпусе с основным микропроцессором и, таким образом, является неотъемлемой частью компьютера.

Основные возможности математического сопроцессора:

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

Тип чисел Знак Степень Целое Мантисса
+∞ 0 11…11 1 00…00
положительные
нормированные
0 00…01 — 11…10 1 00…00 — 11…11
положительные ненормированные 0 00…00 0 00…00 — 11…11
0 0, 1 00…00 0 00…00
отрицательные ненормированные 1 00…00 0 00…00 — 11…11
отрицательные нормированные 1 00…01 — 11…10 1 00…00 — 11…11
-∞ 1 11…11 1 00…00
нечисла
(NaN — Not a number)
* 11…11 1 **…** ≠0

Числа простой и двойной точности ( float ( DD ) и double ( DQ ) соответственно) могут быть представлены только в нормированной форме. При этом бит целой части числа является скрытым и подразумевает логическую 1. Остальные 23 (52) разряда хранят двоичную мантиссу числа.

Числа двойной расширенной точности ( long double ( DT )) могут быть представлены как в нормированной, так и в ненормированной форме, поскольку бит целой части числа не является скрытым и может принимать значения как 0, так и 1.

Основным типом данных, которыми оперирует математический сопроцессор, являются 10-байтные данные ( DT ).

Программная модель сопроцессора

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

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

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

Регистр состояния swr – отражает текущее состояние сопроцессора после выполнения последней команды. В регистре swr содержатся поля, позволяющие определить: какой регистр является текущей вершиной стека сопроцессора, какие исключения возникли после выполнения последней команды, каковы особенности выполнения последней команды (некий аналог регистра флагов основного процессора).

Структурно регистр swr состоит из:

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

Он состоит из:

2-битовое поле управления точностью PC предназначено для выбора длины мантиссы. Возможные значения в этом поле означают:

По умолчанию устанавливается значение поля PC =11.

Бит 12 в регистре cwr физически отсутствует и считывается равным 0.

Регистр тегов twr – представляет собой совокупность двухбитовых полей. Каждое поле соответствует определенному физическому регистру стека и характеризует его текущее состояние. Команды сопроцессора используют этот регистр, например, для того, чтобы определить возможность записи значений в эти регистры. Изменение состояния любого регистра стека отражается на содержимом соответствующего этому регистру 2-битового поля регистра тега. Возможны следующие значения в полях регистра тега:

Принцип работы сопроцессора

Принцип работы сопроцессора совместно с центральным процессором
Процессор и сопроцессор имеют свои раздельные системы команд и форматы обрабатываемых данных. Несмотря на то, что сопроцессор архитектурно представляет собой отдельное вычислительное устройство, он не может существовать отдельно от основного процессора. Процессор и сопроцессор, являясь двумя самостоятельными вычислительными устройствами, могут работать параллельно. Но это распараллеливание распространяется только на выполнение команд. Оба процессора подключены к общей системной шине и имеют доступ к одной и той же информации. Инициирует процесс выборки очередной команды всегда основной процессор. После выборки команда попадает одновременно в оба процессора. Любая команда сопроцессора имеет код операции, первые пять бит, которого имеют значение 11011. Когда код операции начинается этими битами, то основной процессор по дальнейшему содержимому кода операции выясняет, требует ли данная команда обращения к памяти. Если это так, то основной процессор формирует физический адрес операнда и обращается к памяти, после чего содержимое ячейки памяти выставляется на шину данных. Если обращение к памяти не требуется, то основной процессор заканчивает работу над данной командой (не делая попытки ее исполнения) и приступает к декодированию следующей команды из текущего входного командного потока. Выбранная команда попадает в сопроцессор одновременно с основным процессором. Сопроцессор, определив по первым пяти битам, что очередная команда принадлежит его системе команд, начинает ее исполнение. Если команда требует операнды из памяти, то сопроцессор обращается к шине данных за чтением содержимого ячейки памяти, которое к этому моменту предоставлено основным процессором.

Источник

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

12. АРИФМЕТИЧЕСКИЙ СОПРОЦЕССОР

Арифметический сопроцессор значительно (в десятки раз) ускоряет вычисления, связанные с вещественными числами. Он может вычислять такие функции, как синус, косинус, тангенс, логарифмы и т.д. Разумеется, что с помощью сопроцессора можно выполнять и простейшие арифметические операции сложения, вычитания, умножения и деления.

Сопроцессор запускается центральным процессором. После запуска он выполняет все вычисления самостоятельно и параллельно с работой центрального процессора. Если центральный процессор выдает очередную команду сопроцессору в момент времени, когда тот еще не закончил выполнение предыдущей команды, центральный процессор переводится в состояние ожидания. Если же сопроцессор ничем не занят, центральный процессор, выдав команду сопроцессору, продолжает свою работу, не дожидаясь завершения вычисления. Впрочем, есть специальные средства синхронизации (команда FWAIT).

Как программировать сопроцессор?

Команды, предназначенные для выполнения сопроцессором, записываются в программе как обычные машинные команды центрального процессора. Но все эти команды начинаются байта, соответствующего команде центрального процессора ESC.

Встретив такую команду, процессор передает ее на выполнение сопроцессору, а сам продолжает выполнение программы со следующей команды.

Ассемблерные мнемоники всех команд сопроцессора начинаются с буквы F, например: FADD, FDIV, FSUB и т.д. Команды сопроцессора могут адресоваться к операндам, аналогично обычным командам центрального процессора. операндами могут быть либо данные, расположенные в основной памяти компьютера, либо внутренние регистры сопроцессора.

Возможны все виды адресации данных, используемые центральным процессором.

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

12.1. Вещественные числа

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

В общем виде эти числа можно записать следующим образом:

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

Эти числа занимают в памяти, соответственно, 4, 8 или 10 байтов:

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

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

Для наглядности представим мантиссу числа в следующей форме:

Здесь символом n обозначается либо 0, либо 1. Нормализованные числа в самой левой позиции содержат 1, поэтому их можно изобразить еще и в таком виде:

Знак числа, как мы уже говорили, определяется старшим битом.

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

Значение этого числа равно:

Для большей наглядности сведем все возможные представления вещественных чисел в таблицу:

12.2. Целые числа

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

Целое число занимает два байта. Его формат полностью соответствует используемому центральным процессором. Для представления отрицательных чисел используется дополнительный код. Короткое целое и длинное целое имеют аналогичные форматы, но занимают, соответственно, 4 и 8 байтов.

Упакованное десятичное число занимает 10 байтов. Это число содержит 18 десятичных цифр, расположенных по две в каждом байте. Знак упакованного десятичного числа находится в старшем бите самого левого байта. Остальные биты старшего байта должны быть равны 0.

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

Мы подробно рассмотрели формат представления вещественных чисел и отметили, что в этом формате для представления отрицательных чисел используется специальный знаковый бит. Для целых чисел используется дополнительный код.

В дополнительном коде положительные числа содержат нуль в самом старшем бите числа:

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

Например, число +5 в дополнительном коде выглядит следующим образом:

Теперь прибавим к полученному числу +1:

Приведем возможные варианты представления целых чисел:

Упакованное десятичное число имеет следующий вид:

На этом рисунке n0. n17 означают разряды десятичного числа. Они могут изменяться в пределах от 0000 до 1001, т.е. от 0 до 9 в десятичной системе счисления.

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

12.3. Регистры сопроцессора

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

12.3.1. Численные регистры

Численные регистры используются как стек. Регистр состояния в поле ST содержит номер численного регистра, являющего вершиной стека. При выполнении команд в качестве операнда могут выступать численные регистры. В этом случае номер указанного в команде регистра прибавляется к содержимому поля ST регистра состояния и таким образом определяется используемый регистр. Большинство команд после выполнения увеличивают поле ST регистра состояния, как бы записывая результаты своей работы в стек численных регистров.

Вы можете использовать регистры как массив, но в этом случае необходимо заботится о постоянстве поля ST регистра состояния, так как в противном случае номера численных регистров будут изменяться.

12.3.2. Регистр тегов

Этот регистр разделен на восемь двухбитовых полей, которые мы обозначим как TAG0. TAG7. Каждое поле относится к своему численному регистру:

Поля регистра тегов классифицируют содержимое «своего» численного регистра:

00 регистр содержит действительное ненулевое число;
01 в регистре находится нуль;
10 регистр содержит недействительное число (нечисло, бесконечность, неопределенность);
11 пустой неинициализированный регистр.

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

12.3.3. Регистр управления

Регистр управления для сопроцессора 8087 показан на следующем рисунке:

Регистр управления сопроцессоров 80287/80387 и сопроцессора, входящего в состав процессора 80486, имеет аналогичный формат, за исключением того, что бит 7 в нем не используется:

Приведем таблицу масок особых случаев:

IM маска недействительной операции;
DM маска денормализованного результата;
ZM маска деления на нуль;
OM маска переполнения;
UM маска антипереполнения;
PM маска особого случая при неточном результате;
IEM маскирование одновременно всех особых случаев вне зависимости от установки битов 0. 5 регистра управления, этот бит действителен только для сопроцессора 8087

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

Поле PC управляет точностью вычислений в сопроцессоре:

00 использование расширенной точности, этот режим устанавливается при инициализации сопроцессора;
10 округление результата до двойной точности;
00 округление результата до одинарной точности.

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

Двух битовое поле RC задает режим округления при выполнении операций с вещественными числами:

00 округление к ближайшему числу, этот режим устанавливается при инициализации сопроцессора;
01 округление в направлении к отрицательной бесконечности;
10 округление в направлении к положительной бесконечности;
11 округление в направлении к нулю.

Для наибольшего уменьшения ошибок вычислений наиболее целесообразно использовать режим округления в направлении к ближайшему числу. Режим округления в направлении к нулю используется при моделировании целочисленной арифметики.

Поле IC регистра управления предназначен для управления бесконечностью:

В проективном режиме существует только одна бесконечность, она не имеет знака:

12.3.4. Регистр состояния

Поля регистра состояния сопроцессора 8087 показаны на следующем рисунке:

Регистр состояния сопроцессоров 80287/80387 и сопроцессора, входящего в состав процессора 80486, имеет немного другой формат:

Приведем таблицу флажков особых случаев:

IE недействительная операция;
DE денормализованный результат;
ZE деление на нуль;
OE переполнение;
UE антипереполнение;
PE неточный результат.

Для того, чтобы сбросить установившийся флажок, программа должна явным образом установить его в нуль, выполнив команду записи в регистр состояния.

Назначение бита 7 регистра состояния различно для сопроцессора 8087 и сопроцессоров 80287/80387.

Для сопроцессора 8087 этот бит обозначается IR и содержит флаг запроса прерывания при возникновении незамаскированного особого случая. В этом случае флаг устанавливается в 1.

Сопроцессоры 80287/80387 используют бит 7 в качестве флага суммарной ошибки, который устанавливается в 1 при возникновении незамаскированного особого случая.

Поле ST занимает три бита 11. 13 и содержит номер численного регистра, являющегося вершиной стека численных регистров.

12.3.5. Регистры указателя команды и указателя операнда

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

В сопроцессоре 8087 указатель команды содержит 20-разрядный адрес команды, вызвавшей особый случай и код выполняемой в этот момент операции. Адрес команды здесь указывается без учета предшествующих команде префиксов:

Сопроцессоры 80287/80387 в реальном режиме работы имеют такой же формат регистра указателя команд, однако этот указатель показывает на первый префикс команды, вызвавшей особый случай.

Защищенный режим работы центрального процессора и сопроцессора выходит за рамки данной книги, однако для полноты изложения приведем формат указателей и для этого режима. В защищенном режиме адрес состоит из селектора (в какой-то степени соответствует сегментной компоненте адреса реального режима) и смещения. Формат указателя команды для защищенного режима представлен на следующем рисунке:

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

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

Формат указателя операнда для реального режима:

Формат указателя операнда для защищенного режима:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Запись в стек

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

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

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

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

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

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

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

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

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

Обмен

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

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

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

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

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

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

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

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

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

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

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

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

0 остаток от деления, полученный в ST(0), меньше делителя ST(1), команда завершилась полностью;
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»:

Второй вариант библиотеки рассчитан на наличие сопроцессора. Если сопроцессора нет, программа работать не будет. Но если известно, что сопроцессор есть (например, процессор 80486 всегда содержит блок арифметики), то вам имеет смысл использовать именно этот вариант как самый быстродействующий.

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

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

Выходом может быть непосредственное программирование сопроцессора на языке ассемблера. При этом вы можете полностью использовать все возможности сопроцессора и добиться от программы наибольшей эффективности вычислений.

Какие средства можно использовать для составления программ для сопроцессора?

Обычно это или ассемблер MASM (возможно использование TASM), либо интегрированная среда разработки QuickC версии 2.01, содержащая встроенный Quick Assembler.

Приведем пример самой простой программы, подготовленный для трансляции программой Quick Assemler. Эта программа выполняет вычисления по следующей несложной формуле:

Значения x и y задаются в виде констант:

Как убедиться в том, что программа работает правильно?

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

Запустим отладчик CodeView, передав ему в качестве параметра имя приведенной выше программы:

После того, как отладчик запустится, откройте окно регистров сопроцессора, нажав комбинацию клавиш Alt-V-7:

После этого на в нижней части экрана появится окно регистров сопроцессора:

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

Теперь вы видите содержимое регистров управления и состояния (cControl, cStatus), регистра тегов (cTag), регистров указателей команд и данных (Instr Ptr, Data Ptr), код выполняемой команды (Opcode). Отображается также содержимое стека численных регистров (Stack), но пока это поле пустое, так как все численные регистры отмечены в регистре тегов как пустые (код 11).

Нажмите еще раз клавишу F8, выполнив следующую команду программы. Эта команда запишет в стек численных регистров значение переменной x:

Теперь в области регистров стека показано содержимое регистра cST(0), причем как в двоичном виде, так и с использованием экспоненциальной (научной) нотации.

Как и следовало ожидать, регистр ST(0) содержит величину 1.0.

Выполним еще одну команду, прибавляющую к содержимому ST(0) значение 2.0 из переменной y. Теперь регистр ST(0) содержит величину 3.0:

Последняя команда выталкивает из стека хранящееся там значение (3.0) и записывает его в переменную z. Теперь стек численных регистров снова пуст:

Отладчик CodeView обладает мощными средствами динамического просмотра состояния сопроцессора. Однако этот отладчик невозможно использовать для отладки драйверов. Мы уже говорили вам о проблемах, возникающих при отладке драйверов, в первом томе «Библиотеки системного программиста».

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

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

Работа программы основана на использовании команды FSAVE, сохраняющей в памяти содержимое всех регистров сопроцессора. Область сохранения описывается следующей структурой, определенной в файле sysp.inc:

В процессе работы этой программы на каждом шаге на экран выводится дамп содержимого регистров центрального процессора и сопроцессора (пустые численные регистры не отображаются):

12.6. Обработка особых случаев

В арифметическом сопроцессоре имеются два механизма обработки ошибок, возникающих при выполнении различных команд. Первый механизм основан на генерации так называемого прерывания особого случая (INT 10h). Это прерывание вырабатывается в том случае, когда происходит какая-нибудь ошибка (например, деление на нуль) при условии, что соответствующие биты масок особых случаев в регистре управления не установлены. При втором способе обработки ошибок все особые случаи маскируются (соответствующие биты управляющего регистра устанавливаются в единицу) и в случае ошибки сопроцессор в качестве результата возвращает некоторое заранее известное особое значение (нечисло, неопределенность или бесконечность).

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

Рассмотрим возможные особые случаи сопроцессора в реальном режиме.

12.6.1. Неточный результат

В результате выполнения некоторых операций может возникнуть такая ситуация, когда невозможно точно представить результат. Например, при результатом деления числа 1.0 на 3.0 является бесконечная периодическая двоичная дробь 0.010101. Такое число не может быть представлено точно ни в одном формате вещественных чисел.

Обычно неточный результат является результатом округления и может не рассматриваться как ошибка.

12.6.2. Переполнение

Если результат выполнения операции слишком велик и не может быть представлен в формате приемника результата, фиксируется особый случай переполнения.

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

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

12.6.3. Антипереполнение

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

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

12.6.4. Деление на нуль

Этот особый случай возникает при попытке выполнить деление конечного ненулевого числа на нуль.

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

12.6.5. Недействительная операция

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

12.6.6. Денормализованный операнд

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

Если разность (y-x) вызывает антипереполнение и в качестве результата берется нулевое значение, то после вычисления всего выражения получится x. Если же пойти на расширение диапазона представления чисел за счет снижения точности и сформировать результат вычисления разности (y-x) как денормализованное число, выражение будет вычислено правильно и в результате получится y.

Таким образом, иногда целесообразно замаскировать особый случай денормализованного операнда и использовать денормализованные числа. Однако при попытке деления на ненормализованное число или извлечения из него квадратного корня фиксируется особый случай недействительной операции.

Источник

Читайте также:  что такое flex на хоккейной клюшке
Строительный портал