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

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


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

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

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

function Test(First, Second, Third: Integer): Integer; pascal;

мы имеем три 32-битных параметра типа integer, и каждый параметр помещается на стек следующим образом:

First

Second

Third

ESP ->

Инструкция вызова добавляет адрес возврата на стек, и стек теперь выглядит следующим образом:

First

Second



Third

ESP ->

Return Address

Компилятор автоматически генерирует код входа (см. главу 1.2) для сохранения текущего значения регистра EBP и затем копирует регистр ESP в EBP для доступа к фрейму стека:

First

Second

Third

Return Address

EBP, ESP->

Previous EBP

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

First    =     EBP + $10   (EBP + 16)
Second =     EBP + $0C   (EBP + 12)
Third  =     EBP + $08   (EBP + 8)

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

mov EAX,First

Компилятор превратит их в следующий код:

mov EAX,[EBP+0x10]

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

Данные, переданные через стек, всегда занимают 32 бита, даже если вы передаете байт, оставшиеся биты просто не определены.



Содержание  Назад  Вперед