堆叠框架并返回

时间:2020-07-06 21:45:11

标签: assembly x86 callstack stack-frame

因此,我目前正在阅读实用的反向工程_x86,x64,ARM,Windows内核,反向工具和混淆,该书包括以下示例以说明堆栈框架。

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

如果我提出问题的方式有问题,请告诉我。谢谢。

1 个答案:

答案 0 :(得分:2)

指令对

mov esp, ebp
pop ebp

用于恢复调用函数的堆栈帧。也可以通过单条指令完成

leave

但是这可能比使用两条指令要慢(请参阅this post)。

但是mov esp, ebp在这里真的有必要吗?

这取决于在函数中执行的操作。编译器通常会添加此行,因为它会从堆栈中删除局部变量。如果在函数中间使用return,则堆栈上可能还会有其他值,临时结果也可以在堆栈上。想象return是通过以下堆栈分配调用的:

+---------------------------+
|         param 2           |
+---------------------------+
|         param 1           |
+---------------------------+
| old eip (return address)  |
+---------------------------+
| old ebp (last stackframe) | <-- ebp
+---------------------------+
|     local variable 1      |
+---------------------------+
|     local variable 2      |
+---------------------------+
|       interim value       | <-- esp
+---------------------------+

如果寄存器不再足以存储所有值,则可能会出现临时值。并且ebp指向旧的ebp,而不是之后的内存位置(请参阅Does push esp update ESP before or after storing?