为什么我们在装配中的CALLEE中“推动EBP”和“MOV EBP,ESP”?

时间:2016-03-16 20:22:39

标签: assembly x86 x86-64 cpu-registers

为什么我们push ebp作为程序集函数Callee中的第一个动作?

我知道然后我们使用mov edi, [ebp+8]来获取传入的变量,但我们的esp已经指向了Caller函数的返回地址。我们可以使用mov edi, [esp+4]轻松访问传入的变量,或者如果我们按下Callee寄存器,那么mov edi, [esp+16]

那么,为什么在cpu(ebp)中有额外的寄存器,以后你必须在函数中管理?即。

push ebp
mov ebp, esp

...

mov esp, ebp
pop ebp

2 个答案:

答案 0 :(得分:8)

在被调用者中建立新的stack frame,同时保留调用者的堆栈帧。堆栈帧允许使用函数中任何位置的相对于EBP的固定偏移量对传递的参数和局部变量进行一致访问,而ESP可以在函数运行时根据需要继续进行修改。 ESP是一个移动目标,因此使用相对于ESP的动态偏移来访问参数和变量可能很棘手,如果不是不可能的话,这取决于函数如何使用堆栈。创建堆栈帧通常更安全,代价是使用几个字节的堆栈空间来保留指向调用者堆栈帧的指针。

答案 1 :(得分:2)

雷米(Remy)给出的答案是完美的,但是这只是一小部分,您之后可能还会看到的一件事

mov ebp, esp

很有可能看到这样的指令:

sub esp, 20h   ; creating space for local variables with size 20h
sub esp, CCh   ; creating space for local variables with size CCh

有时还带有AND调用(如and esp,0FFFFFFF0h)。这也是处理堆栈的一部分,并且已经完成,因此堆栈可以对齐并可以被16整除。 当然,所有这些都取决于使用的调用约定(cdecl,fastcall,stdcall等)。