Шаг 14.
Передача параметров через стек

    На этом шаге мы рассмотрим общий алгоритм передачи параметров через стек.

    Здесь нам хотелось бы рассмотреть подробнее вопрос о передаче параметров через стек. Мы уже останавливались на нем (шаг 36 в разделе "Assembler: 16-битное программирование"). Это не единственный способ передачи параметров, но именно через стек передаются параметры API-функциям, поэтому на это необходимо обратить внимание. Состояние стека до и после вызова процедуры приводится на рисунке 1.

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


Рис.1. Схема передачи параметров в процедуру (стек растет сверху вниз)

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

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

    Адрес первого параметра определяется как [ЕВР+08Н], что мы уже неоднократно использовали. Адрес первой локальной переменной, если она зарезервирована, определяется как [ЕВР - 4] (имеется в виду переменная типа DWORD). В конце процедуры идут команды:

   MOV ESP, ЕВР 
   POP EBP
   RET M

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

    Такого же результата можно добиться, используя команду

     ENTER N, 0
(заменяет последовательность команд:
    PUSH EBP
    MOV EBP, ESP
    SUB ESP 
) в начале процедуры и
  LEAVE
(заменяет последовательность команд:
   MOV  ESP, ЕВР
   РОР  ЕВР
)

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

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

    Со следующего шага мы перечислим общие принципы построения оконных приложений.




Предыдущий шаг Содержание Следующий шаг