为什么我们在CALLEE in Assembly中"PUSH EBP"和"MOV EBP, ESP"?
Why do we "PUSH EBP" and "MOV EBP, ESP" in the CALLEE in Assembly?
为什么我们push ebp
作为汇编函数的Callee中的第一个动作?
我明白了,然后我们使用mov edi, [ebp+8]
来获取传入的变量,但是我们的esp
已经指向了Caller函数的return地址。我们可以使用 mov edi, [esp+4]
轻松访问传入的变量,或者如果我们压入 Callee 寄存器,则 mov edi, [esp+16]
.
那么,为什么要在 cpu(ebp
)中添加您以后必须在函数中管理的额外寄存器?即
push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp
它正在被调用者中建立一个新的stack frame,同时保留调用者的栈帧。堆栈帧允许使用相对于函数中任何位置 EBP
的固定偏移量来一致地访问传递的参数和局部变量,而 ESP
可以在函数处于 运行 时根据需要自由继续修改. ESP
是一个移动的目标,因此使用相对于 ESP
的动态偏移量访问参数和变量可能会很棘手,如果不是不可能的话,这取决于函数如何使用堆栈。创建堆栈帧通常更安全,代价是使用堆栈的几个字节 space 来保留指向调用者堆栈帧的指针。
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 等)
为什么我们push ebp
作为汇编函数的Callee中的第一个动作?
我明白了,然后我们使用mov edi, [ebp+8]
来获取传入的变量,但是我们的esp
已经指向了Caller函数的return地址。我们可以使用 mov edi, [esp+4]
轻松访问传入的变量,或者如果我们压入 Callee 寄存器,则 mov edi, [esp+16]
.
那么,为什么要在 cpu(ebp
)中添加您以后必须在函数中管理的额外寄存器?即
push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp
它正在被调用者中建立一个新的stack frame,同时保留调用者的栈帧。堆栈帧允许使用相对于函数中任何位置 EBP
的固定偏移量来一致地访问传递的参数和局部变量,而 ESP
可以在函数处于 运行 时根据需要自由继续修改. ESP
是一个移动的目标,因此使用相对于 ESP
的动态偏移量访问参数和变量可能会很棘手,如果不是不可能的话,这取决于函数如何使用堆栈。创建堆栈帧通常更安全,代价是使用堆栈的几个字节 space 来保留指向调用者堆栈帧的指针。
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 等)