Ассемблер для Windows

         

Вопрос о передачи параметров через стек



IV

Здесь мне хотелось бы рассмотреть подробнее вопрос о передачи параметров через стек.

Это не единственный способ передачи параметров, но именно через стек передаются параметры API-функциям, поэтому на это необходимо обратить внимание.

Состояния стека до и после вызова процедуры приводится на Рисунок 1.2.4.

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

При входе в процедуру выполняется стандартная последовательность команд:

PUSH EBP MOV EBP, ESP SUB ESP, N ; N - количество байт для локальных переменных.

Адрес первого параметра определяется как [EBP+8Н], что мы уже неоднократно использовали. Адрес первой локальной переменной, если она зарезервирована, определяется как [EBP-4] (имеется в виду переменная типа DWORD). На ассемблере не очень удобно использовать локальные переменные, и мы не будем резервировать для них место (смотрите, однако, Главу 2.5).

В конце процедуры идут команды:

MOV ESP, EBP POP EBP RET М

Здесь M - объем, взятый у стека для передачи параметров.

Такого же результата можно добиться, используя команду ENTER N,0 (PUSH EBP\MOV EBP,ESP\SUB ESP) в начале процедуры и LEAVE (MOV ESP,EBP\POP EBP) в конце процедуры.

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

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

Существуют два основных подхода (см. [1]). Условно первый подход можно назвать Си-подходом, а второй — Паскаль-подходом.

Первый подход предполагает, что процедура "не знает", сколько параметров находится в стеке. Естественно, в этом случае освобождение стека от параметров должно происходить после команды вызова процедуры, например, с помощью команды POP или команды ADD ESP,N (N - количество байт в параметрах).

Второй подход основан на том, что количество параметров фиксировано, а стек можно освободить в самой процедуре. Это достигается выполнением команды RET N (N - количество байт в параметрах). Как Вы уже, наверное, догадались, вызов функций API осуществяется по второй схеме. Впрочем, есть и исключения, о которых вы узнаете несколько позже (см. Гл. 2.1).




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