Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ПиП МПС(Ассемблер Левицкий экт 4) / Программирование блока FPU в IA

.pdf
Скачиваний:
67
Добавлен:
16.04.2013
Размер:
640.87 Кб
Скачать

Программирование блока FPU в IA-32.

Регистры блока обработки чисел с плавающей точкой

В состав блока FPU процессоров IA-32 входят восемь регистров данных R7-R0, регистр тегов TW, регистры управления FPCR (CW

Control Word) и состояния FPSR (SW – Status Word) (рис. 1), а также указатель инструкции FIP, указатель данных (последнего операнда)

FDP и код последней FPU-операции FOP.

 

 

 

 

 

 

 

Регистры данных FPU

 

 

 

 

 

 

 

(арифметический стек)

Теги

 

79

 

 

 

 

0

 

1

0

 

R0

 

 

 

ST(3)

 

 

 

 

 

 

R1

 

 

 

ST(4)

 

 

 

 

 

 

R2

 

 

 

ST(5)

 

 

 

 

 

 

R3

 

 

 

ST(6)

 

 

 

 

 

 

R4

 

 

 

ST(7)

 

 

 

 

 

 

R5

 

 

 

ST(0)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

R6

 

 

 

ST(1)

 

 

 

 

 

 

R7

 

 

 

ST(2)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14 13

11 10

0

 

 

 

 

 

 

 

 

 

TOP=101

 

SW

 

 

 

CW

TW

Рис. 1. Регистры блока FPU

Регистры данных R7-0 содержат по 80 разрядов, разбитых на три поля: знак, порядок и мантисса, в соответствии с форматом представления чисел с плавающей точкой.

Набор этих регистров организован в виде кольцевого стека, вершина которого определяется содержимым поля ТОР в регистре состояния SW (рис. 2). При выполнении различных операций над содержимым регистров данных расположение вершины стека изменяется.

15

14

13

12

 

 

11

10

9

8

7

6

5

4

3

2

1

0

SW

В

СЗ

 

TOP

 

C2

C1

C0

ES

SF

PE

UE

OE

ZE

DE

IE

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CW

x

x

x

X

 

RC

PC

x

x

PM

UM

OM

ZM

DM

IM

tag7

tag6

 

 

tag5

tag4

tag3

tag2

tag1

tag0

TW

Рис. 2. Форматы содержимого регистров SW, CW, TW

Регистр тегов TW содержит 16-разрядное слово, включающее восемь двухбитных тегов tag7-0 (рис. 2). Каждый тег (признак) характеризует содержимое соответствующего регистра данных R7-0, указывая, является ли регистр пустым (незаполненным) или в нем размещается конечное число, нуль или неопределенное значение (например, бесконечность). Значение тега позволяет проверить содержимое регистра, не проводя анализ хранящихся в нем данных. Значения кодов: 00 – допустимое ненулевое число, 01 – нуль, 10 – специальное значений, 11 – незаполненный регистр.

Регистр состояния SW(FPSR) хранит 16-разрядное слово состояния FPU (рис.2), отдельные биты и поля которого имеют следующее назначение:

Впризнак занятости, включен в состав слова состояния для

совместимости с младшими моделями процессоров; значение B дублирует значение ES – общего признака ошибки FPU;

TOP поле, указывающее вершину арифметического стека (рис.1); содержит номер регистра данных FPU, являющегося в данное время верхним в стеке;

С3-С0 признаки результата, значение которых характеризует результат выполнения инструкции FPU; возможные значения кода в разрядах С3-С0 и их воздействие на работу процессора FPU;

ES общий признак ошибки, принимает значение ES=1, если установился хотя бы один из признаков ошибки операции FPU в шести младших разрядах FPSR; одновременно выдается сигнал FERR# = 0 на соответствующий внешний вывод процессора;

SF признак переполнения стека, принимает значение SF=1 при нарушении нормальной работы арифметического стека; используется совместно с признаком С1: если SF=1, то значение С1=1 указывает на выход за верхнюю границу (переполнение) стека, а С1=0 – на выход за нижнюю границу стека.

Младшие шесть разрядов содержимого FPSR хранят признаки ошибок, возникающих при выполнении инструкций FPU:

РЕ признак нарушения точности; UE признак антипереполнения; ОЕ признак переполнения;

ZE признак деления на нуль;

DE признак денормализованного операнда; IE признак неправильной операции.

Регистр управления CW(FPCR) (рис.2) содержит в младшем байте биты РМ, UM, ОМ, ZM, DM, IM, маскирующие соответствующие признаки ошибок, фиксируемых в регистре состояния FPSR. При единичном значении бита маски запрещается прерывание при возникновении соответствующей ошибки FPU. При нулевом значении бита маски установка соответствующего признака ошибки FPU вызывает прерывание процессора.

Старший байт в регистре управления FPSR определяет режим округления и точность представления результатов вычислений:

RC поле управления округлением, определяет выбор одного из методов округления результата операций FPU;

¾00 – К ближайшему числу (если погрешности округления и в большую, и в меньшую стороны, одинаковы, то округляется к ближайшему четному, т.е. так, чтобы самый младший значащий разряд был нулевым).

¾01 – К минус-бесконечности

¾10 – К плюс-бесконечности

¾11 – К нулю

PC поле управления точностью, задает точность представления результатов арифметических операций FPU: одинарную (23 разряда мантиссы, 8 разрядов порядка), двойную (52 разряда мантиссы, 11 разрядов порядка) или расширенную (64 разряда мантиссы, 15 разрядов порядка).

00 – Одинарная

01 – (не используется)

10 – Двойная

11 – Расширенная

Поле PC учитывается только при выполнении инструкций FADD, FSUB, FDIV, FMUL, FSQRT. Для остальных инструкций FPU используется расширенная точность.

Регистры – указатели инструкции FIP и данных FDP служат для идентификации инструкции, вызвавшей ошибку операции FPU. Содержимое этих регистров зависит от режима работы процессора. В реальном режиме при возникновении ошибки при выполнении инструкции FPU в эти регистры заносятся адрес данной инструкции и адрес использованного операнда. В защищенном режиме в них заносятся селекторы сегментов и относительные адреса инструкции и операнда. Эта информация используется подпрограммой обработки прерываний для выяснения причины ошибки FPU.

FPU хранит код операции последней выполненной инструкции в 11битовом регистре кода операции (FOP). Здесь хранятся только первый и второй байты кода операции (после всех префиксов), причем первые 5 битов первого байта не хранятся т.к. для FPU операций, они всегда равны 11011B.

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

Данные типа, получившего в языке С название long double, которые занимают десять байтов и состоят из знака s, положительной мантиссы m и смещенного порядка с. Порядок определяется по общей формуле для всех типов данных с плавающей точкой с = 2n-1 + р, где п - количество разрядов для представления порядка, р - значение двоичного порядка для представления мантиссы числа с единицей в целой части. Более наглядным может быть определение значения смещения порядка всеми двоичными единицами, кроме старшего разряда. Разрядная сетка числовых регистров сопроцессора имеет параметры п=15, с=16367 и может быть представлена в виде:

s ссссссс

сссссссс

 

m.mm...m

 

mmmmmmmm

 

79

72

71

64

63

 

8

7

0

Регистровый формат для long double

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

данных соответствует принципу – по меньшему адресу записывается менее весомый байт. Так данные в памяти, сформированные по директиве

_longDoubleArg dt 23.23;

кодируются десятком байтов - 40 03 D9 D7 0А 3D 70 A3 D7 0А, который размещается в памяти в обратной последовательности:

mmmmmmmm

 

m.mm...m

 

сссссссс

s ссссссс

7

0

15 8 … 56

63

71

64

79

72

Формат в памяти для long double

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

 

 

Таблица 1

Тип данных

Характеристики

Применение значений

Денормализо-

с=0000,

Минимальные с плавающей

ванные

m=значение

точкой. Специальные с

 

 

фиксированной точкой

Ненормализо-

c=7FFF,

Промежуточные с плавающей

ванные

m=0.XX...X

точкой

+0

с=0000, s=0, m=0

Нулевые данные и результаты

-0

c=0000,s=l,m=0

Нулевые результаты

+00

c=7FFF, s=0, m=0

Результаты переполнений

- 00

c=7FFF,s=l,m=0

Результаты переполнений

Неопределенность

c=7FFF,m=1.10...0

Результаты особых случаев

Нечисленные

c=7FFF,m=l.lX...X

Специальные данные

 

 

пользователя

Ранее в FPU выделялись проективный и афинный режимы обработки специальных значений. В проективном режиме константы +0 и -0, а также +и - не различаются и сравнение числа с бесконечностью приводит к недействительной операции, а в афинном – указанные пары значений различаются и возможны сравнения обычных значений с бесконечностью. Однако, начиная с i486, проективный режим исключен.

Данные типа, называемого в языке C float, а в языке Pascal - Single и занимающего четыре байта и n=8, а с=127 и имеют нормализованное представление с размещением точки, отделяющей целую часть мантиссы от дробной, после старшего двоичного значащего разряда. Единичная-целая часть мантиссы в памяти не записывается:

mmmmmmmm

 

mmmmmmmm

 

c.mmmmmmm

s ссссссс

7

0

15

8

23

16

32

24

Формат в памяти для float

Пример:

_floatArg dd 23.23

Значение константы в шестнадцатиричном представлении имеет вид: 41 b9 d7 0a, при загрузке в память байты размещаются в обратном порядке.

Данные типа double занимают восемь байтов и имеют n=11, с=1023

ипредставляются в памяти следующим образом:

mmmmmmmm mm...mm сссс.mmmm s ссссссс

7

0 15 8

33 41 55

48 79

72

Формат в памяти для double

Пример:

_doubleArg dq 23.23

Значение константы в шестнадцатеричном представлении имеет вид: 40 37 3а e1 47 ае 14 7b, при загрузке в память байты размещаются в обратном порядке.

Базовые команды математического сопроцессора

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

коды сопроцессора и организует его взаимодействие с главным процессором. Названия этих команд начинаются с буквы F, а следующие буквы определяют тип операции. Все команды пересылок данных в процессор с необходимыми преобразованиями данных имеют в названии буквы LD и выполняются путем размещения данных с плавающей точкой в верхушки стека с предварительным изменением текущего значения указателя стека st и преобразованием во внутреннюю десятибайтную форму с плавающей точкой. Базовая команда FLD перемещает данные как из регистров с плавающей точкой, указанных в командах Ассемблера в форме st[i], где i - номер нужного регистра относительно верхушки стека, так и с любой области главной памяти и задается по формату:

[метка:] fld операнд-источник

Команды FILD и FBLD задаются программистом для преобразования целочисленных данных в форму с плавающей точкой при загрузке четырех-, восьми- и десятибайтных данных в сопроцессор из памяти. Буква I задает целочисленные двоичные данные, буква В - десятибайтные двоично-десятичные данные в bcd-коде. Команды FST и FIST задают копирование содержимого верхушки стека st[0] с преобразованиями в формат, соответствующий определению области приемника. Команды извлечения из стека и преобразования данных: FSTP, FISTP и FBSTP после преобразования данных освобождают соответствующий регистр стека и смещают указатель стека, причем операндом в них может быть регистр сопроцессора. Команда FXCH задает обмен регистра верхушки стека st[0] с регистром, заданным в операнде. Группа безоперандных команд используется для загрузки распространенных констант в верхушку стека FLDZ - 0, FLD1 - 1,

FLDPI - π, FLDLG2 - lg2, FLDLN2 - ln2, FLDL2T -log2l0 логарифм числа 10 по основанию 2, FLDL2E - log2e.

Аргументы стандартных математических функций языка С могут быть переданы в подпрограмму через верхушку стека процессора в виде числа с плавающей точкой в формате длинного вещественного представления (float double), для чего в вызывающей последовательности для одноместной функции можно использовать следующие команды, включая команды сопроцессора:

FLD

x

; Загрузка аргумента в стек сопроцессора

SUB

sp,8

; Подготовка места

в стеке главного процессора

МОV

bp,sp

; Подготовка

указателя

FSTP

qword ptr[bp] ; Пересылка аргумента в стек из

 

; сопроцессора

CALL имя входной точки функции в библиотечном модуле

ADD sp,8

; Освобождение стека

Результат вычисления стандартной функции также в формате длинного вещественного (float double) будет размещен в сегменте данных, а его внутрисегментный адрес в подпрограммах используемой библиотеки возвращается при выходе из подпрограммы в аккумуляторе АХ. Таким образом, для приема и сохранения результата можно использовать такие команды:

MOV bх,ах ; Копирование внутрисегментного адреса FLD qword ptr[bx] ;Пересылка результата в сопроцессор FSTP имя области приемника результата

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

 

 

 

 

Таблица 2

 

Команда

1-й операнд

2-й операнд

Стек

 

Fxxx память

верхушка стека

операнд из

без изменений

 

 

 

 

команды

 

 

FIxxx память

верхушка стека

целый операнд

без изменений

 

 

 

 

из команды

 

 

Fxxx

st,st[i]

верхушка стека

регистр стека

без изменений

 

Fxxx

st[i],st

регистр стека

верхушка стека

без изменений

 

FxxxP st[i],st

регистр стека

верхушка стека

удаление из

 

 

 

 

 

верхушки

 

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

Безоперандная команда Рххх реализуется как FxxxP st[i],st. Здесь

ххх– означает содержание операции из следующего списка:

¾ADD – сложение;

¾SUB – вычитание второго аргумента из первого;

¾MUL – умножение;

¾DIV – деление первого аргумента на второй;

¾SUBR – реверсивное вычитание (первого аргумента из второго);

¾DIVR – реверсивное деление.

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

FLD

f1

;Загрузка первого слагаемого

FLD

f2

;3агрузка второго слагаемого

FADD

 

;Суммирование и освобождение стека сопроцессора

FSTP

result ; Запоминание результата в памяти

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

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

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

FINIT ; Начальный сброс сопроцессора

FLDCW слово с начальном состоянием регистра CW

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

FSTCW

слово-приемник регистра управления

FLDCW

слово-источник: регистра управления

FSTSW

слово-приемник регистра состояния

FLDSW

слово-источник регистра состояния

FSTENV

блок-приемник состояния среды сопроцессора

FLDENV

блок-источник состояния среди сопроцессора

FSAVE

блок-приемник состояния среды и регистров сопроцессора

FRSTOR

блок-источник состояния среди и регистров сопроцессора

FCLEX

; Сброс флагов особых случаев

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

регистров сопроцессора, так и внутренних регистров сопроцессора, недоступных по другим командам:

¾регистр управления CW (смещение 0 для 16- и 32-битовых режимов);

¾регистр состояния SW (смещение 2 для 16- и 4 – для 32-битовых режимов);

¾слово тэгов, в котором каждая пара битов отображает текущее состояние физического регистра с плавающей точкой (смещение

4/8);

¾указатель команды IP (6/0Ch);

¾селектор CS и/или код операции (8/10h);

¾смещение операнда IP (0ah/14h);

¾селектор операнда (0Ch/18h).

Таким образом, для 16-битового режима полный размер области сохранения составляет 94 байта, а 32-битового - 108 байтов. Отметим, что пустые регистры в стеке сопроцессора могут возникать после выполнения команд декремента стека сопроцессора FDECSTP и освобождения регистров FFREE st[i].

Для составления связующих элементов программ и контроля за взаимодействием сопроцессора с центральным процессором целесообразно использовать элементарные команды математического сопроцессора, включенные в язык Ассемблера. Основу взаимодействия составляет использование центральным процессором и сопроцессором общей последовательности команд. В принципе для управления математическим сопроцессором и взаимодействия с центральным процессором используются команды центрального процессора ESC и WAIT. Единственная команда, подключающая сопроцессор к работе имеет мнемонику ESC представляется во внутримашинном двоичном формате:

15 14 13 12 11 10

9 8

7 6

5 4 3

2 1 0

смещение данных

1

1

0

1

1

 

ccc

mod

ccc

r/m

(d8/d16)

Структура кода FPU-инструкции

Здесь буквами ссс обозначены биты кода операции сопроцессора, mod модификация операндов, r/m регистр или указатель типа операнда в памяти. В машинной форме после основной части команды с указателями модификаций адресов в памяти могут находиться двухбайтный адрес для прямой адресации, однобайтное d8 или двухбайтное d16 смещение. Регистровые команды сопроцессора имеют сокращенные форматы.