汇编语言ENTER和LEAVE指令:创建和结束堆栈帧
ENTER 指令为被调用过程自动创建堆栈帧。它为局部变量保留堆栈空间,把 EBP 入栈。具体来说,它执行三个操作:
ENTER 有两个操作数:第一个是常数,定义为局部变量保存的堆栈空间字节数;第二个定义了过程的词法嵌套级。
【示例 1】下面的例子声明了一个没有局部变量的过程:
如果要使用 ENTER 指令,那么强烈建议在同一个过程的结尾处同时使用 LEAVE 指令。否则,为局部变量保留的堆栈空间就可能无法释放。这将会导致 RET 指令从堆栈中弹出错误的返回地址。
- 把 EBP 入栈 (push ebp)
- 把 EBP 设置为堆栈帧的基址 (mov ebp, esp)
- 为局部变量保留空间 (sub esp, numbytes)
ENTER 有两个操作数:第一个是常数,定义为局部变量保存的堆栈空间字节数;第二个定义了过程的词法嵌套级。
ENTER numbytes, nestinglevel
这两个操作数都是立即数。Numbytes 总是向上舍入为 4 的倍数,以便 ESP 对齐双字边界。Nestinglevel 确定了从主调过程堆栈帧复制到当前帧的堆栈帧指针的个数。在示例程序中,nestinglevel 总是为 0。【示例 1】下面的例子声明了一个没有局部变量的过程:
MySub PROC
enter 0,0
MySub PROC
push ebp
mov ebp, esp
MySub PROC
enter 8,0
MySub PROC
push ebp
mov ebp,esp
sub esp,8
如果要使用 ENTER 指令,那么强烈建议在同一个过程的结尾处同时使用 LEAVE 指令。否则,为局部变量保留的堆栈空间就可能无法释放。这将会导致 RET 指令从堆栈中弹出错误的返回地址。
LEAVE 指令
LEAVE 指令结束一个过程的堆栈帧。它反转了之前的 ENTER 指令操作:恢复了过程被调用时 ESP 和 EBP 的值。再次以 MySub 过程为例,现在可以编码如下:
MySub PROC
enter 8,0
.
.
leave
ret
MySub ENDP
MySub PROC
push ebp
mov ebp, esp
sub esp, 8
.
.
mov esp, ebp
pop ebp
ret
MySub ENDP