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

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

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

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

FINIT ; Начальный сброс без контроля особых случаев FHCLEX ; Сброс флагов особых случаев без их контроля

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

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

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

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

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

Для организации ветвлений и проверки условий окончания циклов используются группа команд сравнения сопроцессора и команды передачи слова состояния в центральный процессор. FCOM – сравнивает st[0] с операндом, а FICOM – с целым операндом из памяти; FCOMP - сравнивает содержимое st[0] с операндом, после чего исключает его из стека сопроцессора, a FICOMP делает то же действие при сравнении с целочисленным операндом; FCOMPP - сравнивает два верхних регистра стека st[0] и st[1] с последующим их исключением из стека.

FTST – сравнивает st[0] с 0. Перечисленные команды меняют содержимое регистра состояния в соответствии с результатом вычитания второго операнда из первого и могут быть использованы для организации условной передачи управления по арифметическим отношениям.

Результат

С3

С2

С0

ST[0] > X

0

0

0

ST[0] < X

0

0

1

ST[0] = X

1

0

0

Не сравнимы

1

1

1

Коды результата операции сравнения в регистре SW

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

 

 

 

 

 

 

 

 

 

 

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

 

 

 

 

 

 

 

 

15

14 13

 

12

11

10

9

 

8

7

 

. . .

0

 

 

 

 

 

 

 

C3

 

 

 

 

 

C2

C1

C0

 

 

 

 

 

 

 

 

 

 

 

 

Инструкция FSTSW

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Регистр AX (AH,AL)

 

 

 

 

 

 

15

14 13

 

12

11

10

9

 

8

7

 

. . .

0

 

SW FPU

FLAGS

 

 

 

 

 

 

 

 

 

C3

 

 

 

 

 

C2

C1

C0

 

 

 

 

 

 

 

 

C0

CF

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C1

---

 

 

 

Инструкция SAF

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C2

PF

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C3

ZF

 

 

Регистр FLAGS

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

. . .

 

8 7 6 5 4 3 2 1 0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ZF

 

 

 

 

 

 

PF

 

1

CF

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Перемещение кодов условий из регистра управления FPU в регистр флагов CPU.

В старших моделях IA-32 реализована группа команд сравнения FCOMI и FCOMIP, которые, выполняют сравнение аналогично командам FCOM и FCOMI, но устанавливают флаги не в FPSR, а прямо в регистре EFLAGS центрального процессора.

Результат

ZF

PF

CF

ST[0] > X

0

0

0

ST[0] < X

0

0

1

ST[0] = X

1

0

0

Не сравнимы

1

1

1

Коды результата операции сравнения в регистре EFLAGS

Таким образом полностью соблюдается соответствие: C0ÙCF, C2ÙPF и C3ÙZF.

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

Условные переходы по результатам сравнений в сопроцессоре можно организовать макроопределением следующего вида:

FJ

MACRO

cd,lb ; Прототип макровызова

FSTSW

stsw

; Запись в память регистра состояния

FWAIT

 

;FPU и команды центрального процессора

 

; Ожидание окончания пересылки

MOV ah,byte ptr stsw+1 ;Копирование регистра состояния

SAHF

; Сохранение содержимого регистра ah

J&CD lb

; в регистре флагов

; Условный переход

ENDM

 

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

[метка:] FJ условие_перехода, метка_перехода

Первый операнд макрокоманды, определяет условие перехода теми же буквами, которые используются в командах условных переходов по результатам беззнаковой арифметики, то есть а – больше, b – меньше, n

– отрицание и e – равенство. Команда FXAM позволяет получить гораздо больше информации о содержимом st[0], но дает особое кодирование битов признака результатов, и может использоваться также для инициализации кодов условия.

Содержимое st[0]

С3

С2

С0

Поддерживаемый формат

0

0

0

Не-число

0

0

1

Нормализованное число

0

1

0

Бесконечность

0

1

1

Ноль

1

0

0

Пусто

1

0

1

Денормализованное число

1

1

0

Коды результата анализа содержимого регистра st[0], командой FXAMP.

Таким образом, синхронизация параллельной работы центрального процессора и математического сопроцессора реализуется достаточно просто и в большинстве случаев прозрачно для программиста. Другой случай необходимости синхронизации связан с возникновением особых ситуаций в сопроцессоре. Сопроцессор при незамаскированной особой ситуации формирует сигнал прерывания к центральному процессору по одному из трех номеров векторов прерываний 07h - при отсутствии сопроцессора и 10h или 75h - при ошибках и особых случаях в сопроцессоре, в зависимости от структуры аппаратной части.

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

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

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

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

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

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

Построим пример реализации программы для экспоненциальной функции еx, вычисляемой по формуле:

e x =

x i

, где 0! = 1. В этом случае отношение (i+1)-го члена

i =0

i!

ряда ai+1 к i-му аi имеет вид: R = аi+1i = х/i.

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

_Ехр PROC

PUSH BP ;Стандартное сохранение базового указателя стека MOV BP,SP ;Установка нового значения базового указателя

FLD QWORD PTR[BP+4] ; Загрузка начального значения

FLD

st

 

; суммы х

; Загрузка значения 0-го члена ряда

FLD

st

; Загрузка х для вычисления постоянного

MOV

cntr,1

;

множителя

 

; Запись начального значения счетчика

LSi:FMUL st[1]

; Домножение на - х*x

FIMUL cntr

 

; Домножение на 2i-1

INC

cntr

 

; Инкремент счетчика

FIDIV cntr

 

; Деление на 2i+1

FADD

st[2],st

; Накопление суммы членов ряда

СМР

cntr,10

; Контроль предельного значения счетчика

JB

LSi

; Переход, если расчет не закончен

FINCSTP

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

FINCSTP

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

FSTP

result

; Сохранение результата

MOV

AX,offset DGROUP:result

POP

BP ; Восстановление базового указателя стека

RET

; Выход из подпрограммы

_Ехр ENDP

Здесь cntr должно быть определено как WORD, result как QWORD в сегменте данных. Команды FINCSTP и FDECSTP применяются для баланса стека сопроцессора и изменения значения его указателя, добавляя или вычитая единицу из указателя стека соответственно.

Аналогичным образом вычисляются и ряды для других функций, но с учётом их особенностей. Например, для синуса и косинуса R=(х*х)/2i(2i+1), т.е. здесь нужны манипуляции над числами, связанными с 2i. Эти числа удобнее всего строить, основываясь на хранении 2i (и 2i+1) в целой форме с последующими инкрементами в оперативной памяти.

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

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

FSQRT – заменяет аргумент в st[0] значением квадратного корня. FABS – заменяет содержимое st[0] его абсолютным значением. FCHS – смена знака содержимого st[0].

FRNDINT – округляет содержимое st[0] до целого значения. FXTRACT – расщепляет содержимое st[0] на два числа: несмещен-

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

Команда FSCALE после FXTRACT восстанавливает начальное число, но не восстанавливает указатель стека.

FSCALE - к значению порядка в st[0] добавляется целая часть числа из st[1] и таким образом восстанавливаются исходные данные команды FXTRACT, для компенсации изменений указателя стека нужно дополнительно выполнить команду FSTP st[1].

FCOS – заменяет аргумент в st[0] значением синуса для аргумента в радианах в пределах -263.. 263.

FSIN – заменяет аргумент в st[0] значением синуса для аргумента в радианах в пределах -263.. 263;

FSINCOS – заменяет аргумент в st[0] значением синуса для аргумента в радианах в пределах -263.. 263, затем выполняет --st и помещает в новую верхушку стека значения косинуса того же аргумента (выполняется быстрее отдельных функций).

FPREM - вычисляет частичный остаток от деления st[0] на st[1] и размещает его в st[0]. Знак st[0] не изменяется, а если для получения окончательного результата достаточно меньше, чем 64 масштабированные вычитания, то остаток, меньший модуля со знаком делимого, будет записан в st[0]. При этом три младших бита частного, позволяющие определить квадрант аргумента при делении на π/2 помещаются в разряды С3, C1 и С0 регистра SW.

FPREM1 – то же, что и FPREM, но абсолютная величина остатка меньше половины модуля в соответствии со стандартом IEEE-754.

Процессоры ix87 могут вычислить любую элементарную трансцендентную функцию с аргументом, точность представления которого определяется содержимым регистра управления, и последующей выдачей результата такой же точности. В названиях команд и их описаниях принято обозначать аргументы, содержащиеся в st[0] как X, а в st[1] - как Y. Результаты, формирующиеся в st[0], будем обозначать как x, а в st[1] - как y. Для упрощения восприятия этих команд, представленных в табл. 3, следует учитывать, что они разработаны с возможностью получения полного результата с помощью самой простой и естественной дополнительной команды.

Вычисление тригонометрических функций основано на выполнении команды FPTAN - нахождения частичного тангенса, которая в качестве результата дает два таких числа х и у, что у/х = tg X. Число у заменяет старое содержимое st[0], а число х включается в стек дополнительно.

Таблица 3

Мнемоника

Название операции

Ограничения на

команды

Вычислительная формула

аргументы

 

 

|Х| <263 :386

FPTAN

Частичный тангенс --st, у/х=tg Х

FPATAN

Частичный арктангенс

нет ограничений

 

++st, x=arctg(Y/X)

 

 

FYL2X

Вычисление логарифма

Х > 0

 

++st, Y*log2X

 

 

FYL2XP1

Вычисление логарифма

|X|<1 – 1/2

 

++st, Y*log2(X+1)

 

1<=Х<=1

F2XM1

Вычисление Х =2x -1

Вычисление тригонометрических функций первых математических сопроцессоров было основано на выполнении команды FPTAN – нахождения частичного тангенса, которая формирует результат в виде таких двух чисел х и у, что у/х=tgX. Число у заменяет старое содержимое st[0], а число х добавляется к стеку дополнительно. Для вычисления значений тригонометрических функций сначала нужно отделить знак аргумента Х от значения; потом поделить на период π для тангенса, если х >= π/2, то изменить знак результата и значение аргумента на х-π, вычислить аргумент z=х/2 и использовать формулы:

sinz =

2y/ x

;

cosz =

1(y / x)2

;

tgz =

 

 

2y / x

;

1+(y/ x)2

1+(y / x)2

1

(y / x)2

 

 

 

 

 

 

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

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

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

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

Рассмотрим программирование вычисления тригонометрических функций с использованием их выражений через тангенс половинного угла. Эти формулы имеют неограниченный диапазон определения. Тангенс половинного угла имеет относительно аргумента z период π/2 и если организовать изменение знака, то достаточно использовать половинный аргумент.

При программировании тригонометрических функций диапазон значений аргумента можно свести к допустимому командой FPREM или проверить с помощью команды FXAM, так как он должен быть нормализованным и находиться в диапазоне 0<st[0]<π/4. Если аргумент Х лежит вне этого диапазона, то в начале программы необходимо выполнить преобразования аргумента к нужному диапазону и запомнить данные для обратного преобразования. Существуют несколько путей преобразования с использованием формул через тангенс половинного угла и формул приведения значений тригонометрических функций. Наиболее эффективны пути, нашедшие

наиболее полное отражение в системе команд сопроцессора.

 

Для функции tgX можно использовать 4 преобразования:

(1)

Х<0; S=signX; Y=|Х|; tgX= StgY;

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

Y>π; Z=Y – n π; tgY = tgZ; (2)

Здесь устраняется n-кратное повторение периода и дополнительных действий по восстановлению результата не требуется. Следующие два преобразования могут быть проведены в безусловной форме, так как модифицированный аргумент лежит в диапазоне 0 Y π.

U=Z/2;

tgZ=(2tgU)/(1-tg2U);

(3)

V=U/2;

tgU=(2tgV)/(1-tg2V);

(4)

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

tgV=2xy/(x2-y2) и u=2xy; v = x2-y2

(5)

где и/ v = tg V .

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

sinY = (2u/v) / (1-(u/v)2); cosY = (1-(u/v)2) / (1+(u/v)2); cosecY = (1+(u/v)2) / 2uv; secY = (1+(u/v)2) / (1-(u/v)2);

Пример процедуры вычисления тангенса, построенной по рассмотренным формулам:

_tg

PROC

;Стандартное сохранение указателя стека

PUSH

BP

MOV

BP,SP

;Установка нового значения указателя

FLDPI

 

; Загрузка числа π

FLD

QWORD PTR[BP+4] ; Загрузка аргумента х

FTST

 

 

FSTSW stsw

 

PUSH

stsw

; Исключение периода

rm: PREM

FJ

p,rm

; Циклическое исключение остатка

FLD1

st,st

; Формирование числа 2

FADD

FXCH

st[1]

; Деление на 4

FSCALE

 

FPTAN

st[1]

; Вычисление составляющих тангенса

FLD

; Дублирование числителя

FMUL

st,st

; Квадрат числителя (y*y)

FXCH

st[1]

; Обмен со знаменателем

FMUL

st[2],st; Вычисление x*y

FMUL

st,st

; Вычисление x*x

FSUBP

st[1],st; Получение v

FMUL

st,st[2]; Получение u

FLD

st

; Дублирование числителя u

FMUL

st,st

; Квадрат числителя (u*u)

FXCH

st[2]

; Обмен со знаменателем

FMUL

st[1],st; Вычисление (u*v)

FMUL

st,st

; Вычисление (v*v)

FSUBP

st[2],st; Получение знаменателя тангенса

FMULP

st[2],st; Получение числителя тангенса

;Для следующей команды нужно предусмотреть

;защиту от особых ситуаций

FDIVP

st[1],st;

Получение значения тангенса

FSTP

result ;

Сохранение результата

MOV

AX,offset DGROUP:result

POP

BP ; Восстановление базового указателя стека

RET

; Выход из подпрограммы

_tg ENDP