Использование ассемблера в Дельфи


         

Возврат информации через стек сопроцессора


Функции, которые возвращают результат с плавающей запятой, просто должны возвращать результат в ST(0). Ниже вы найдете пример. Помните, что сопроцессор обрабатывает внутри все числа, как 10-байтные расширенные числа. Указывая формат результата (single, double, extended, comp, currency, и т.д.) мы только указываем, как число будет записано в ST(0) и затем в память. В примере функции CalcRelatMass показано это. Передаются два параметра, масса и скорость тела и производится расчет относительной массы, согласно теории относительности. Оба параметра: масса (m) и скорость (v), передаются в функцию как double, результат так же возвращается как double.

function CalcRelatMass(m,v: Double): Double; register;

const

LightVelocity: Integer = 299792500;

asm

{Расчет относительной массы по следующей фформуле:

Result = m / Sqrt(1-v²/c²), где c = скорость света,

m масса и v скорость движения объекта}

fild LightVelocity

fild LightVelocity

fmulp {расчет c²}

fld v



fld v

fmulp {расчет v²}

fxch

fdivp {v²/c²}

fld1

fxch

fsubp {ST(0)=1-(v²/c²)}

fsqrt {корень ST(0)}

fld m

fxch

fdivp {деление массы на корень результата}

end;

Оба параметра, m и v, передаются в функцию через стек. Поскольку они типа double, то они занимают по 8 байт стека, который выглядит следующим образом:

EBP+0x10 m

EBP+0x08 v

EBP+0x04 адрес возврата

EBP ->   предыдущий EBP

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

Вы можете изменять точность и режим округления вычислений путем изменения контрольного слова процессора. Хотя вы точно знаете, что делаете, но это не поощряется, поскольку смена контрольного слова влияет на все вычисления для всего вашего приложения. Проблему обостряет то, что некоторые DLL также изменяют контрольное слово. Это иногда может привести к непредсказуемым результатам  или различным результатам в зависимости от Операционной Системы, на которой запускается программа или в зависимости от того, какие версии DLL реально используются. Как заметил Robert Lee в одном из сообщений в группе новостей, вы должны особенно избегать этого, путем загрузки контрольного слова из глобальной переменной Default8087CW (объявлена в модуле System) до выполнения важных процедур.

Так же очень важно полное понимание природы чисел с плавающей запятой при использовании их внутри вашего кода. Я написал отдельную статью, в которой обсуждается основы. Статья доступна на моих страницах по Дельфи на сайте http://www.optimalcode.com/Guido/fpv.html.



Содержание раздела