Справочник по языку Ассемблера IBM PC

ENTER


(setup parameter block for ENTERing procedure)

Установка кадра стека для параметров процедуры

 

Схема команды:  enter loc_size,lex_lev 

Назначение: установка границы в стеке для локальных переменных процедуры.


Алгоритм работы:

поместить текущее значение регистра ebp/bp в стек;

сохранить текущее значение esp/sp в промежуточной переменной fp (имя переменной выбрано случайно);

если лексический уровень вложенности (операнд lex_lev) не равен нулю, то (lex_lev–1) раз делать следующее:



в зависимости от установленного режима адресации use16 или use32 выполнить вычитание (bp–2) или (ebp–4) и записать результат обратно в ebp/bp;

сохранить значение ebp/bp в стеке;

сохранить в стеке значение промежуточной переменной fp;

записать значение промежуточной переменной fp в регистр ebp/bp;

уменьшить значение регистра esp/sp на величину, заданную первым операндом, минус размер области локальных переменных loc_size: esp/sp=(esp/sp)–loc_size.

Состояние флагов после выполнения команды:

выполнение команды не влияет на флаги

Применение:


Команда enter специально введена в систему команд микропроцессора для поддержки блочно-структурированных языков высокого уровня типа Pascal или С. В этих языках программа разбивается на блоки. В блоках можно описать свои собственные (локальные) идентификаторы, которые не могут быть использованы вне этого блока. К примеру, на рисунке ниже в виде блоков изображена структура некоторой программы.

Изображение структуры некоторой программы в виде блоков

В правом верхнем углу каждого блока (процедуры) стоит номер лексического уровня вложенности этого блока относительно других блоков программы. Большинство блочно-структурированных языков в качестве основного метода распределения памяти для переменных в блоках используют автоматическое распределение памяти. Это означает, что при входе в блок (вызове процедуры и т. п.) в некотором месте памяти (или в стеке) выделяется область памяти для переменных этого блока (ее можно назвать областью инициализации). После выхода из этого блока связь программы с этой областью теряется, то есть эти переменные становятся недоступными. Но если, как в нашем примере, в этой процедуре есть вложенные блоки (процедуры), то для некоторого внутреннего блока (например, C) могут быть доступны области инициализации (переменные) блоков, объемлющих данный блок. В нашем примере для блока C доступны также переменные блоков B и A, но не D. Возникает вопрос: как же программа, находясь в конкретной точке своего выполнения, может отслеживать то, какие области инициализации ей доступны? Это делается с помощью структуры данных, называемой дисплеем. Дисплей содержит указатели на самую последнюю область текущего блока и на области инициализации всех блоков, объемлющих данный блок в программе. Например, если в программе A была вызвана сначала процедура B, а затем C, то дисплей содержит указатели на области инициализации A, B и C (см. рисунок ниже).




Если после этого вызвать процедуру D (в то время как B и C еще не завершены), то картина изменится.



После того как некоторый блок (процедура) завершает свою работу, ее область инициализации удаляется из памяти (стека) и одновременно соответствующим образом корректируется дисплей. Большинство языков высокого уровня хранят локальные данные блоков в стеке. Эти переменные называют еще автоматическими или динамическими. Память для них резервируется путем уменьшения значения регистра-указателя стека esp/sp на величину, равную длине области, занимаемой этими динамическими переменными. Доступ к этим переменным осуществляется посредством регистра ebp/bp. Если один блок вложен в другой, то для его динамических (локальных) переменных также выделяется место (кадр) в стеке, но в этот кадр помещается указатель на кадр стека для включающего его блока. Команды enter и leave как раз и позволяют поддержать в языке ассемблера принципы работы с переменными блоков как в блочно-структурированных языках. Дисплей организуется с помощью второго операнда команды enter и стека. Например, в начале работы главной процедуры A и после вызова процедуры B кадр стека будет выглядеть так.



Соответственно, после вызова процедур C и D стек будет выглядеть, как показано ниже.



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

.286 proc1   proc ;зарезервировать в стеке место для локальных переменных ;proc1 16 байт ;лексический уровень вложенности 0         enter   16,0 ...         leave         ret proc1   endp         

См. также: урок 14 и команды ,


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