如果我像这样设置堆栈
push rbp;
mov rbp, rsp;
sub rsp, 64;
我需要
吗?mov rsp, rbp;
pop rbp;
ret 64;
或仅
mov rsp, rbp;
pop rbp;
ret;
答案 0 :(得分:1)
这样就足够了:
mov rsp, rbp;
pop rbp;
ret;
因为它将恢复rsp的旧值(无论sub
指令中减少了多少)。
答案 1 :(得分:1)
第二个,如果你打算使用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
因此,当此函数返回其调用者时,堆栈指针比其CALL
之前的位置提前64字节。如果您的函数是使用STD调用约定定义的(callee删除了参数),那么这很好。我认为这不是你想要的,因为你似乎认为ret 64用于恢复为自动变量分配的堆栈的64字节。