М а т е м а т и ч е с к и й

с о п р о ц е с с о р

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

Для обработки данных с плавающей точкой служит специальное устройство — математический сопроцессор (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

Программирование на Машинно-Ориентированных Языках.
Преподаватель: Коробов С.А.