汇编语言ENTER和LEAVE指令:创建和结束堆栈帧

< 上一页LEA指令 LOCAL伪指令下一页 >
ENTER 指令为被调用过程自动创建堆栈帧。它为局部变量保留堆栈空间,把 EBP 入栈。具体来说,它执行三个操作:
  • 把 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

【示例 2】ENTER 指令为局部变量保留了 8 个字节的堆栈空间:

MySub PROC
    enter 8,0

它与如下指令等效:

MySub PROC
    push ebp
    mov ebp,esp
    sub esp,8

下图为执行 ENTER 指令前后的堆栈示意图。

执行ENTER指令后的堆栈

如果要使用 ENTER 指令,那么强烈建议在同一个过程的结尾处同时使用 LEAVE 指令。否则,为局部变量保留的堆栈空间就可能无法释放。这将会导致 RET 指令从堆栈中弹出错误的返回地址。

LEAVE 指令

LEAVE 指令结束一个过程的堆栈帧。它反转了之前的 ENTER 指令操作:恢复了过程被调用时 ESP 和 EBP 的值。再次以 MySub 过程为例,现在可以编码如下:

MySub PROC
    enter 8,0
    .
    .
    leave
    ret
MySub ENDP

下面是与之等效的指令序列,其功能是在堆栈中保存和删除 8 个字节的局部变量:

MySub PROC
    push ebp
    mov ebp, esp
    sub esp, 8
    .
    .
    mov esp, ebp
    pop ebp
    ret
MySub ENDP

< 上一页LEA指令 LOCAL伪指令下一页 >