【发布时间】:2020-10-27 02:32:39
【问题描述】:
所以我目前正在阅读 Practical reverse engineering_x86, x64, ARM, Windows Kernel, reversing tools, and obfuscation 这本书包括以下示例来解释堆栈框架。
addme(x, y)
01: 004113A0 55 push ebp
02: 004113A1 8B EC mov ebp, esp
03: ...
04: 004113BE 0F BF 45 08 movsx eax, word ptr [ebp+8]
05: 004113C2 0F BF 4D 0C movsx ecx, word ptr [ebp+0Ch]
06: 004113C6 03 C1 add eax, ecx
07: ...
08: 004113CB 8B E5 mov esp, ebp
09: 004113CD 5D pop ebp
10: 004113CE C3 retn
函数调用
01: 004129F3 50 push eax ;param2
02: ...
03: 004129F8 51 push ecx ;param1
04: 004129F9 E8 F1 E7 FF FF call addme
05: 004129FE 83 C4 08 add esp, 8
我知道在 addme 函数的第 10 行,我们执行 mov ebp, esp 来为当前函数启动一个新的堆栈帧,但我不明白我们为什么要调用 mov esp, ebp 就在流行音乐之前。如果我理解正确,这是调用 mov esp, ebp 之前堆栈的当前状态。
TOP
**************************
* param2 *
**************************
* param1 *
**************************
* return addrs *
**************************
* old edp *
**************************
esp and edp are pointing after odl edp.
那么为什么会调用 mov esp, ebp?
如果我提出问题的方式有问题,请告诉我。谢谢。
【问题讨论】:
-
在这种情况下没有必要因为
esp没有被修改。否则,其目的将是解放当地人。请注意,标准堆栈帧不是强制性的,并且在优化代码中经常不使用。 -
一个更聪明的编译器会意识到它可以只使用
pop %ebp而不是在这种情况下使用leave。 (事实上 GCC 甚至在调试模式下也进行了优化)。我假设在未显示的部分内部没有sub esp, 1234或push/call(将东西留在堆栈上以供收尾清理)。
标签: assembly x86 callstack stack-frame