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;
?
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;
?
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.
It is enough to do:
As it will restore the old value of rsp ( regardless of how much was decreased in the
sub
instruction ).