Balancing the stack

225 views Asked by At

If I setup the stack like this

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

do I need to

mov rsp, rbp;
pop rbp;
ret 64;

or only

mov rsp, rbp;
pop rbp;
ret;

?

2

There are 2 answers

1
MByD On

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

2
mcleod_ideafix On

The second one, if you are going to use the C calling convention (caller removes the arguments).

mov rsp, rbp;
pop rbp;
ret;

If you would use the first epilog, this is what happens with your stack:

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

So when this function returns to its caller, the stack pointer is 64 bytes ahead of its position just before the CALL to this function. This is fine, if your function is defined with the STD calling convention (callee removes the arguments). I think that this is not what you want, as you seem to think that the ret 64 is for restoring the 64 bytes the stack allocated for automatic variables.