0

如果我像这样设置堆栈

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

我需要吗

mov rsp, rbp;
pop rbp;
ret 64;

或仅

mov rsp, rbp;
pop rbp;
ret;

?

4

2 回答 2

2

第二个,如果您要使用 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 个字节。

于 2013-12-21T14:31:59.237 回答
1

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 ).

于 2013-12-21T14:26:29.243 回答