Математический сопроцессор.
Для обработки данных с плавающей точкой служит специальное устройство —
математический сопроцессор (FPU — Floating Point Unit).
С момента своего возникновения сопроцессор расширял вычислительные возможности
основного процессора i8086 (i80286, i80386, i80486) и сначала был
выполнен в виде отдельной микросхемы i8087 (i80287, i80387, i80487).
Его присутствие в первых моделях процессора было не обязательным.
Если сопроцессора не было, то его команды можно было эмулировать программным путем,
что немного ухудшало производительность основного процессора. Начиная с семейства процессоров
i486DX, сопроцессор стал составной частью основного процессора.
Современный сопроцессор обеспечивает полную поддержку стандартов IEEE-754 и
IEEE-854 по представлению и обработке чисел с плавающей точкой. Он может
выполнять трансцендентные операции (вычисление тригонометрических функций, логарифмов
и проч.) с большой точностью.
Сопроцессор выполняет все вычисления в 80-битном расширенном вещественном формате, а 16-,
32-, 64-битные данные используются для обмена данными и могут применяться в командах сопроцессора
как операнды (приемник или источник).
Типы обычных данных сопроцессора.
Тип данных |
Длина (бит) |
Количество значащих цифр |
Диапазон представления |
Целое слово |
16 |
4-5 |
-32768 … 32767 |
Короткое целое |
32 |
9-10 |
-2147483648 … 2147483647 |
Длинное целое |
64 |
18-19 |
-9223372036854775808 … 9223372036854775807 |
Упакованное двоично-десятичное |
80 |
18 |
-999999999999999999 … 999999999999999999 |
Короткое вещественное |
32 |
7-8 |
1.175494351e-38 … 3.402823466e+38 |
Длинное вещественное |
64 |
15-16 |
2.2250738585072014e-307 … 1.7976931348623158+308 |
Расширенное вещественное |
80 |
19-20 |
3.3621031431431120935063e-4932 … 1.189731495357231765e+4932 |
Особые числа.
Кроме обычных чисел, спецификация стандарта IEEE предусматривает несколько
специальных форматов, которые могут получиться в результате выполнения математических
операций сопроцессора.
- Положительный ноль — все биты числа сброшены в ноль.
- Отрицательный ноль — знаковый бит равен 1, остальные биты числа сброшены в ноль.
- Положительная бесконечность — знаковый бит равен 0, все биты экспоненты установлены
в 1, а биты мантиссы сброшены в 0.
- Отрицательная бесконечность — знаковый бит равен 1, все биты экспоненты
установлены в 1, а биты мантиссы сброшены в 0.
- Денормализованные числа — все биты экспоненты сброшены в 0. Эти числа
позволяют представлять очень маленькие числа при вычислениях с расширенной точностью.
- Неопределенность — знаковый бит равен 1, первый бит мантиссы равен 1
(для 80-разрядных чисел первые два бита равны 11), остальные биты мантиссы
сброшены в ноль, все биты экспоненты установлены в 1.
- He-число типа SNAN (сигнальное)
- Не-число типа QNAN (тихое)
- Неподдерживаемое число — все остальные ситуации
Регистры: 8-дынные, 5-вспомогательные.
Назначение регистров |
Биты |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
CWR |
Регистр управления (Control Word Register) |
SWR |
Регистр состояния сопроцессора (Status Word Register) |
TWR |
Слово признаков-тегов (Tags Word Register) |
FIP (32 бита) |
Регистр указателя последней выполненной команды (Floating Instruction Pointer) |
FDP (32 бита) |
Регистр, где хранится адрес операнда указателя последней
выполненной команды (Floating Data Pointer) |
R0 - ST(2) (80 бит) |
Расширенное вещественное или любое другое допустимое данное сопроцессора |
R1 - ST(3) (80 бит) |
Расширенное вещественное или любое другое допустимое данное сопроцессора |
R6 - (TOP) вершина стека ST или ST(0) (80 бит) |
Расширенное вещественное или любое другое допустимое данное сопроцессора |
R7 - ST(1) (80 бит) |
Расширенное вещественное или любое другое допустимое данное сопроцессора |
Регистры данных.
Регистры данных сопроцессора R0-R7 имеют длину 80 бит (т.е. пять 16-разрядных слов)
и рассматриваются как круговой стек, вершина которого (ТОР) называется ST или
ST(0) и является плавающей. Принцип работы с круговым стеком сопроцессора аналогичен
обычному калькулятору. Любая команда загрузки данных сопроцессора автоматически перемещает вершину
стека сопроцессора: ТОР=ТОР+1. На таблице свурху показана гипотетическая ситуация, когда в
результате выполнения какой-то команды вершиной стека стал регистр R6. Остальные регистры
распределяются подряд по кругу: R7-ST(1), R0-ST(2),...,R5-ST(7). Это и есть их текущие имена
ST(i), i=l,...,7 на момент выполнения данной команды сопроцессора. Если в этих регистрах
есть данные, то они могут служить операндами в командах сопроцессора.
Обращаться напрямую к регистрам R0-R7 нельзя.
Система команд.
Система команд сопроцессора достаточно простая, если знать ключ и немного понимать английский язык.
Для их подключения нужно сделать следующее:
Воспользоваться одной из директив Ассемблера: .8087, .287 (.286р), .387(.386 .487 (.486р).
Необходимо иметь в виду, что не все команды сопроцессора, к сожалению, совместимы сверху вниз. Кроме того,
директива использования процессора .х86р предполагает компиляцию и работу программы в 32-разрядном
режиме. Поэтому результаты расчета, выполненные с использованием команд младших моделей сопроцессора, могут
отличаться от результатов, полученных на старших моделях.
Сделать инициализацию сопроцессора с помощью команды FINIT
При компиляции использовать ДОПОЛНИТЕЛЬНЫЙ ключ /r
или /е
(Emulated or Real floating-point instructions). Таким образом, теперь вызов компилятора Ассемблера
для стыковки с C++ может иметь следующий вид:
tasm.exe Name.asm /I /r /ml
Условные обозначения для команд базового сопроцессора.
Базовый сопроцессор i8087 имеет 69 базовых команд, которые подчиняются
следующим закономерностям:
- Все они начинаются на букву F (Floating).
- Вторая буква может быть связана с форматом обрабатываемых чисел:
- I (Integer) — целые числа;
- В (Binary-coded decimal) — упакованное двоично-десятичное число (BCD).
Для вещественных чисел специальная буква НЕ выделяется.
- Далее идет мнемонический код операции (МКОП), например:
- LD (LoaD) — загрузить данное в вершину стека ST;
- ST (STore) — выгрузить данное из вершины стека ST и
уже известные нам команды
ADD
, MUL
, DIV
и т.п.
- Заканчиваться команда может буквой R (Reversed — реверсная операция) и/или Р
(Pop — вытолкнуть результат из стека и освободить вершину стека ST).
МКОП |
Обычная операция |
Реверсная операция |
SUB |
Приемник = Приемник - Источник |
Приемник = Приемник - Источник |
DIV |
Приемник = Приемник / Источник |
Приемник = Приемник / Источник |
Сопроцессоры более поздних моделей, начиная с i80387, немного нарушили эту стройную
систему условных обозначений, но зато увеличили функциональные возможности команд по обработке
данных.
Команды пересылки данных.
Все команды этой группы имеют один операнд: либо источник, либо приемник.
Загрузка или извлечение информации происходит в/из вершины стека ST(0).
Обычно вершину стека обозначают через ST, и в командах этой группы она явно
в операндах НЕ присутствует.
Команда |
Тип данных |
Характеристика операнда |
Пример |
Команды загрузки данных в стек |
FLD источник |
Вещественное |
Переменная в ОЗУ или ST(i), i=0,..,7 |
FLD а FLD ST(5) |
FBLD источник |
Типа BCD |
Переменная в ОЗУ |
FBLD аВс |
FILD источник |
Целое |
Переменная в ОЗУ |
FELD ka |
Команды копирования данных из стека |
FST приемник |
Вещественное |
Переменная в ОЗУ или ST(i), i=1,...,7. |
FST аp FST ST(1) |
FIST приемник |
Целое |
Переменная в ОЗУ |
FIST kab |
Команды извлечения данных из стека с освобождением вершины стека |
FSTP приемник |
Вещественное |
Переменная в ОЗУ или ST(i), i=1,...,7. |
FSTP аp FSTP ST(5) |
FBSTP приемник |
Типа BCD |
Переменная в ОЗУ |
FBSTP ppp |
FISTP приемник |
Целое |
Переменная в ОЗУ |
FISTP kabP |
Команда обмена содержимого источника с ST(0) |
FXCH источник |
Если источник НЕ указан, то считается, что он соответствует ST(1). |
ST(i), i=1,...,7. |
FXCH FXCH ST(4) |
Команды загрузки констант.
Команды этой группы помешают в вершину стека ST(0) часто используемые константы.
Начиная с сопроцессора i80387, эти константы хранятся в более точном формате.
Команды операндов не имеют.
Команда |
Назначение |
FLDI |
Поместить в ST(0) число 1.0 |
FLDZ |
Поместить в ST(0) число +0.0 |
FLDPI |
Поместить в ST(0) число р |
FLDL2E |
Поместить в ST(0) число, равное log2 e |
FLDL2T |
Поместите в ST(0) число, равное log2 10 |
FLDLN2 |
Поместить в ST(0) число, равное ln 2 |
FLDLG2 |
Поместить в ST(0) число, равное lg 2 |
Арифметические команды.
Команды базовой арифметики
Команда |
Тип данных |
Алгоритм выполнения |
Команды сложения |
FADD приемник, источник |
Вещественное |
Приемник = приемник + источник |
FADDP приемник, источник |
Вещественное |
FIADD источник |
Целое |
Команды обычного вычитания |
FSUB приемник, источник |
Вещественное |
Приемник = приемник - источник |
FSUBP приемник, источник |
Вещественное |
FISUB источник |
Целое |
Команды реверсного (обратного) вычитания |
FSUBR приемник, источник |
Вещественное |
Приемник = источник - приемник |
FSUBRP приемник, источник |
Вещественное |
FISUBR источник |
Целое |
Команды умножения |
FMUL приемник, источник |
Вещественное |
Приемник = источник * приемник |
FMULP приемник, источник |
Вещественное |
FTMUL источник |
Целое |
Команды обычного деления |
FDIV приемник, источник |
Вещественное |
Приемник = приемник / источник |
FDIVP приемник, источник |
Вещественное |
FIDIV источник |
Целое |
Команды реверсного (обратного) деления |
FDIVR приемник, источник |
Вещественное |
Приемник = источник / приемник |
FDIVRP приемник, источник |
Вещественное |
FIDIVR источник |
Целое |
Специальные арифметические команды
Команда |
Назначение |
Алгоритм выполнения |
FPREM |
Нахождение частичного остатка от деления путем последовательного вычитания
64 раза содержимого ST(1) из ST(0) |
ST(0)=ocтаток[ST(0)/ST( 1)]
Формируется флаг С2 регистра управления CWR:
С2=0 — получен точный остаток от деления, т.е. остаток
С2=1 — точный остаток НЕ получен (получен частичный остаток) |
FPREM1 (i80387) |
Нахождение частичного остатка от деления в стандарте IEEE —
округление к ближайшему целому |
FABS |
Нахождение абсолютного значения |
ST(0) = abs(ST(0)) |
FSQRT |
Нахождение корня квадратного |
ST(0) = sqrt(ST(0)) |
FCHS |
Изменение знака |
ST(0) = -ST(0) |
FRNDINT |
Округление до целого |
Содержимое ST(0) округляется до целого в соответствии с битами
RC регистра управления сопроцессором CWR |
FXTRACT |
Извлечь экспоненту и мантиссу числа |
Число ==> ST(0); ST(0) = мантисса числа; ST(I) — экспонента числа |
FSCALE |
Команда, обратная FXTRACT |
ST(0) <== мантисса числа; ST(1) <== экспонента числа; ST(0)=ST(0)* 2ST(1) |
Пример.
; Вычислить действительные корни квадратного уравнения:
; a*x*x + b*x + c = 0
.387
.MODEL LARGE,C
.DATA
EXTRN C a:DWORD,b:DWORD,c:DWORD,x1:DWORD,x2:DWORD,d:DWORD
EXTRN C ac:DWORD,bb:DWORD
.CODE
PUBLIC quadr
four DD 4.
two DD 2.
quadr PROC C FAR |
FINIT |
; иниц. 8087 |
|
;------------ST(0)------------ |
! ------------ST(1)------------! |
FILD b |
; b |
! ? |
FMUL ST(0),ST(0) |
; b*b |
! ? |
FST bb |
; копиpование веpшины стека ==> bb |
FILD a |
; a |
! b*b |
FMUL four |
; 4*a |
! b*b |
FIMUL c |
; 4*a*c |
! b*b |
FST ac |
; копиpование веpшины стека ==> ac |
FSUBP ST(1),ST(0) |
; ;d=b*b-4*a*c |
! ? |
FST d |
; копиpование веpшины стека ==> d |
FSQRT |
; sqrt(d) |
! ? |
FLD ST(0)
|
; sqrt(d) |
! sqrt(d) |
FCHS |
; -sqrt(d) |
! sqrt(d) |
FIADD b |
; b-sqrt(d) |
! sqrt(d) |
FCHS |
; -b+sqrt(d) |
! sqrt(d) |
FXCH ST(1) |
; sqrt(d) |
! -b+sqrt(d) |
FIADD b |
; b+sqrt(d) |
! -b+sqrt(d) |
FCHS |
; -b-sqrt(d) |
! -b+sqrt(d) |
FIDIV a |
; -b-sqrt(d)/a |
! -b+sqrt(d) |
FDIV two |
; -b-sqrt(d)/a/2 |
! -b+sqrt(d) |
FSTP x2 |
; -b+sqrt(d) |
! ? |
FIDIV a |
; -b+sqrt(d)/a |
! -b+sqrt(d) |
FDIV two |
; -b+sqrt(d)/a/2 |
! ? |
FSTP x1 |
; ? |
! ? |
RET
QUADR ENDP
END |
|
|
Лабораторная работа №5