平衡堆栈

时间:2013-12-21 14:24:06

标签: assembly stack x86-64

如果我像这样设置堆栈

push rbp;
mov rbp, rsp;
sub rsp, 64;

我需要

吗?
mov rsp, rbp;
pop rbp;
ret 64;

或仅

mov rsp, rbp;
pop rbp;
ret;

2 个答案:

答案 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字节。