【问题标题】:Is mov esp, ebp really necessary?mov esp, ebp 真的有必要吗?
【发布时间】:2021-04-29 13:01:10
【问题描述】:

考虑到堆栈向下增长(低地址)并假设 intel 语法。

使用以下sn-p:

main:

    push ebp 
    mov ebp, esp
    push ebx
    push esi
    push edi

   ; ... do stuff

    pop edi
    pop esi
    pop ebx
    mov esp, ebp    ; <- necessary? i.e. can be omitted?
    pop ebp
    ret

我知道在进入函数之前,当前堆栈指针被保存到基指针(=堆栈帧)中,但是从指令中我发现mov esp, ebp 是多余的;通过弹出3个寄存器然后进入基指针不是你增加堆栈指针(更高地址),因此,同时,恢复 堆栈指针?

【问题讨论】:

  • 如果值已经恢复如您的示例中,则没有必要。
  • 这里似乎不需要它,但如果您减少esp 为局部变量腾出空间,则通常需要它。
  • @interjay 你能举个例子吗?我也会接受它作为答案
  • 我只能想象在push ebp 之后和mov ebp, esp 之前的push 指令(但不确定)

标签: assembly x86 x86-64


【解决方案1】:

在您提供的代码中,mov esp, ebp 不是必需的,因为esp 的原始值在pop 指令之后恢复并且已经等于ebp

但一般来说,如果减少了esp 以为局部变量腾出空间,则可能需要此指令。例如:

some_function:
    push ebp 
    mov ebp, esp
    sub esp, 256      ; allocate 256 bytes for local variables

    ;  ... function body

    mov esp, ebp      ; restore esp
    pop ebp
    ret

这些是 x86 代码中使用的标准 "function prologue" and "function epilogue"

【讨论】:

  • 编译器 do 在冗余的情况下将其排除在外(并且他们没有完全忽略帧指针)。如果他们没有将 ESP/RSP 从保存的 EBP/RBP 中移开,他们只需使用 pop ebp 而不是 leave (gcc) 或 mov/pop (clang)。所以 OP 的代码不是你在真正的编译器输出中看到的,只能在样板教程中看到。
猜你喜欢
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 2012-10-10
  • 2018-04-05
  • 2021-01-25
相关资源
最近更新 更多