Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПиП МПС(Ассемблер Левицкий экт 4) / MProc / M3 / Программирование блока FPU в IA.doc
Скачиваний:
81
Добавлен:
16.04.2013
Размер:
250 Кб
Скачать
☆

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

Мнемоника команды

Название операции Вычислительная формула

Ограничения на аргументы

FPTAN

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

|Х| <263 :386

FPATAN

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

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

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

FYL2X

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

++st, Y*log2X

Х > 0

FYL2XP1

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

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

|X|<1 – 1/2

F2XM1

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

1<=Х<=1

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

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

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

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

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

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

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

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

Х<0; S=signX; Y=|Х|; tgX= StgY; (1)

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

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

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

FXCH st[1]

FSCALE ; Деление на 4

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

FLD st[1] ; Дублирование числителя

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

Кроме рассмотренного способа тригонометрические функции могут вычисляться либо через тангенс половинного угла по формуле (3), либо через тангенс полного угла по формулам:

ctg x = 1 / tg x;

(7)

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

Команда FPATAN вычисляет arctg(st[1]/st[0])=arctg(Y/X). Два верхних элемента извлекаются из стека, а результат включается в стек. Операнды этой команды должны удовлетворять условию 0<Y<Х, иначе необходимо использовать формулы приведения:

arctg х = -arctg(-х), arctg х = π/2 - arctg (1/ x ). (8)

Остальные обратные тригонометрические функции находятся с по­мощью команд FPATAN, FSQRT и таких формул:

arctg z = arctg (Y/X);

arcctg z = arctg(1/z) = arctg(X/Y);

В этих формулах z - аргумент вычисляемой функции, X, Y - значения составного аргумента в регистрах st[0], st[1] перед выполнением команды FPATAN, результат которой помещается в вершину стека.

Формулы для вычисления логарифмических функций:

log2x => FYL2X при Y => FLD1, X => FLD х;

ln(x) => FYL2X при Y => FLDLN2, X => FLD x;

lg(x) => FYL2X при Y => FLDLG2, X => FLD x.

Команда FYL2X вычисляет st(1)*log2(st[0]) при st[0]>0. Оба операнда извлекаются из стека, а затем результат помещается в стек. Команды FLDL2E, FLDL2T загружают константы со значением двоичных логарифмов числа e и числа 10.

Еще одна логарифмическая команда FYL2XP1 вычисляет st[1](st[0]+1) при st[0]<1-1/2 и используется для вычисления обратных гиперболических функций. Команда F2XM1 вычисляет 2st[0]-1, причем для аргумента должно выполняться условие: |st[0]|1

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

arsh х = sign x *ln 2* log2(1 + z ), где

arch x = ln2*log2(1+z), где z = x-1+ и х>1;

arth x = sign x - ln2 * log2(1+z), где z = 2|x| / (1-| x |) и -1< x< 1.

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

arcth x =arth (1/x); arcsh x =arsh (1/x); arsch x =arch (1/х).

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

ch(x) = 0.5(e|x| + 1/e|x|);

cth(x) = 1/th(x); csh(x) = 1/sh(x);

sch(x) = 1/ch(x);

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

2x = (2x-1) + 1 => F2XM1(x) + 1;

ex = 1 + 2x log2(e)-1 => 1+F2XM1(x*FLD2E);

10x = 1 + 2x log2(10)-1 => 1+F2XM1(x*FLD2T);

xy = 1 + 2y log2(x)-1 => 1+F2XM1(FYL2X(y,x)).

Например, последнюю функцию можно реализовать следующей последовательностью команд:

FLD1 ; Загрузка единицы

FLD x ; Загрузка основания

FLD y ; Загрузка показателя

FYL2X ; Вычисление логарифма результата

FXTRACT ; Расщепление на порядок и мантиссу

FXCH st[1]

FISTP tem ; Сохранение порядка показателя

; В должно быть выделено целочисленное поле tmp

FIDIV qrt ; Сведение диапазона делением на 4

; Поле qrt должно содержать целую константу 4

F2XM1 ; Вычисление показательной функции

FADD ; Коррекция эксп-ты от мантиссы на 1

MOV CX,2 ; Корректирующая добавка к порядку

ADD CX,tem ; Определение числа возведений в квадрат

m1:FMUL st,st[0] ; Циклическое повторение

LOOP m1 ; возведений в квадрат

К сожалению нельзя после команды FYL2X просто поставить F2XM1 с FADD и на этом завершить процедуру. Дело в том, что аргумент команды F2XM1 должен быть по модулю меньше 1. Поэтому приходится применять эту команду только к мантиссе результата, а порядок учитывать через процедуру циклического возведения в квадрат. Для гарантии, упомянутая мантисса результата, заранее делится на 4, что потом компенсируется корректирующей добавкой к порядку.