问题描述
push rbp
mov rbp,rsp
mov DWORD PTR [rbp-0x4],edi
在汇编函数序言中,不是 push rbp
已经将其值移动到 rsp
了吗?为什么 mov rbp,rsp
指令再次将相同的 rsp
值移动到 rbp
?是必要的还是多余的?
解决方法
push rbp
不是已经将其值移动到 rsp
了吗?
没有。 push rbp
相当于:
sub rsp,8 ; but without setting FLAGS
mov [rsp],rbp
不多也不少,就像推送任何其他寄存器 (https://www.felixcloutier.com/x86/push) 一样。这将 rbp
存储到 rsp
指向的内存中,但不会修改除 rsp-=8
之外的寄存器。这不是 enter
instruction。
您可能已经知道这一点,但 rbp
用作帧指针。 mov rbp,rsp
将前一个堆栈顶部保存到 rbp
,这个顶部现在用作当前堆栈帧的底部。
但这会产生一个问题:如果 rbp
已被修改,那么之前的堆栈帧呢?由于栈帧被修改了,所以这个函数返回后,rbp
会出现错误的位置,事情会变得很糟糕。
这就是 push rbp
的用武之地。它在修改之前保存 rbp
的值,以便在函数返回之前,rbp
的原始值可以立即弹出rbp
所以前一个堆栈帧保持正常。
(或者换句话说,rbp
是调用保留的,因此我们需要保存/恢复它,作为将其设置为堆栈帧的帧指针的一部分。)
mov rbp,rsp 将 rsp 中的当前值移入 rbp。
认为: 您想保存最后一个堆栈帧并构建另一个。
intel(上面的代码)和 at&t 语法之间也存在差异。
英特尔: mov dest,source