如果我像这样设置堆栈
push rbp;
mov rbp, rsp;
sub rsp, 64;
我需要吗
mov rsp, rbp;
pop rbp;
ret 64;
或仅
mov rsp, rbp;
pop rbp;
ret;
?
如果我像这样设置堆栈
push rbp;
mov rbp, rsp;
sub rsp, 64;
我需要吗
mov rsp, rbp;
pop rbp;
ret 64;
或仅
mov rsp, rbp;
pop rbp;
ret;
?
第二个,如果您要使用 C 调用约定(调用者删除参数)。
mov rsp, rbp;
pop rbp;
ret;
如果您使用第一个 Epilog,您的堆栈会发生以下情况:
push rbp; ;RSP = RSP - 8 (1) |
mov rbp, rsp; ;Keep RSP (2) | Your prologue. Nothing wrong here.
sub rsp, 64; ;RSP = RSP - 64 |
...
...
mov rsp, rbp; ;Retrieve RSP from (2)
pop rbp; ;RSP = RSP + 8. Now it's at the same address as before (1)
ret 64; ;Return, but after that, add 64 to RSP
所以当这个函数返回给它的调用者时,堆栈指针比它在这个函数之前的位置提前了 64 个字节CALL
。这很好,如果您的函数是使用 STD 调用约定定义的(被调用者删除参数)。我认为这不是您想要的,因为您似乎认为 ret 64 是用于恢复堆栈为自动变量分配的 64 个字节。
It is enough to do:
mov rsp, rbp;
pop rbp;
ret;
As it will restore the old value of rsp ( regardless of how much was decreased in the sub
instruction ).