Enter
создает кадр стека, а leave
уничтожает кадр стека. С параметрами 0,0
для enter
они в основном эквивалентны:
; enter
push ebp
mov ebp, esp
; leave
mov esp, ebp
pop ebp
Хотя он и не используется в опубликованном вами коде, enter
поддерживает выполнение немного большего, чем простая комбинация push / mov, показанная выше. Первый параметр enter
указывает объем пространства, выделяемого для локальных переменных. Например, enter 5, 0
примерно эквивалентно:
push ebp
mov ebp, esp
sub esp, 5
Enter
также поддерживает такие языки, как Pascal, которые могут использовать вложенные функции / процедуры:
procedure X;
procedure Y;
begin
{ ... }
end
begin
{ ... }
end
В таком случае Y
имеет доступ не только к своим собственным локальным переменным, но также ко всем переменным, локальным для X
. Они могут быть вложены на произвольную глубину, так что вы можете иметь Z
внутри Y
, который имел доступ к своим собственным локальным переменным, а также переменным Y
и переменным X
. Второй параметр enter
указывает глубину вложенности, поэтому X
будет использовать enter Sx, 0
, Y
будет использовать enter Sy, 1
, а Z
будет использовать enter Sz, 2
(где Sx
, Sy
и Sz
означает размер переменных, локальных для X
, Y
и Z
соответственно).
Это создаст цепочку стековых фреймов для предоставления Z
доступа к локальным переменным Y
и X
и т. Д. Это становится довольно нетривиальным, если функции являются рекурсивными, поэтому вызов Z
не может просто подняться по стеку к двум самым последним кадрам стека - ему необходимо пропустить кадры стека из предыдущих вызовов самого себя, и Вернитесь непосредственно к стеку фреймов для лексической родительской функции / процедуры, которая отличается от вызывающего в случае рекурсии.
Эта сложность также объясняет, почему C и C ++ запрещают вложенные функции. Учитывая наличие ввода / вывода, их довольно легко поддерживать на процессорах Intel, но может быть значительно сложнее на многих других процессорах, которые не имеют такой прямой поддержки.
Это также, по крайней мере, помогает объяснить еще одну ... особенность enter
- для используемого здесь тривиального случая (т. Е. enter 0, 0
) он немного медленнее, чем эквивалент, использующий push
/ mov
.