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


         

Передача информации через регистр


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

Текущее поколение процессоров, для которых написана данная статья, обычно называются как Intel Pentium процессоры, имеет регистры шириной в 32 бита. Когда передаваемая информация не полностью использует регистр (для типов слово и байт), то используется, только часть регистра, байты используют младшие восемь бит, например al и для слов младшее слово, например ax. Указатели всегда 32-битные (по крайней мере, пока не появятся 64-битные процессоры) и занимают весь регистр полностью, например eax. В случае переменных типа байт и слово оставшаяся часть регистра не определена и вы не должны делать никаких предположений относительно его содержимого. Например, при передаче байта в функцию, через регистр al, остальные 24 бита регистра eax не определены и вы, конечно, не можете рассчитывать на то, что они равны нулю. Вы просто можете использовать инструкцию and для  очистки оставшихся бит.

and EAX,$FF {беззнаковый байт в AL, очистка старших 24 бит}

или

and EAX,$FFFF {беззнаковое слово в AX, очистка старших 16 бит}

Когда вы передаете знаковые параметры (ShortInt или SmallInt), вы должны расширить их с учетом знака. Для расширения знака для байтового параметра до двойного слова, вы должны использовать две инструкции:

cbw  {расширение al до ax}

cwde {расширение ax до EAX}

Для демонстрации, напишите следующую тестовую подпрограмму:

function Test(Value: ShortInt ): LongInt; register;

asm

end;

Разместите кнопку и метку на форме и поместите следующий код в обработчик OnClick:



var

I : ShortInt ;

begin

I := -7;

Label1.Caption := IntToStr(Test(I));

end;

Запустите проект и нажмите кнопку. Тестовая процедура принимает параметр типа ShortInt  через al. И возвращает результат типа integer через регистр EAX, который возвращает результат неизменным. Вы можете просто считать, что EAX имеет неизмененное значение при возврате. Теперь изменим функцию следующим образом и запустим проект снова на выполнение:

function Test(Value: ShortInt ): LongInt; register;

asm

cbw

cwde

end;

Единственным соглашением, согласно которому регистры используются для передачи параметров, это соглашение с ключевым словом register, которое также является соглашением по умолчанию. Все другие соглашения используют стек для передачи параметров в функции или процедуры. И конечно, если вы передаете более двух или трех параметров, то стек также используется для передачи оставшихся параметров. В заключение, некоторые параметры всегда передаются через стек - это указатели методов, которые в действительности состоят из двух 32-битных указателей и параметров с плавающей запятой. Обзор можно найти в таблице 2.



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