isn't push rbp
already moves its value to rsp
?
No. push rbp
is equivalent to:
sub rsp, 8 ; but without setting FLAGS
mov [rsp], rbp
No more, no less, just like pushing any other register (https://www.felixcloutier.com/x86/push). This stores rbp
to memory pointed-to by rsp
, but doesn't modify registers other than rsp-=8
. It's not an enter
instruction.
You may already know this, but rbp
is used as a frame pointer. mov rbp, rsp
saves the previous top of the stack to rbp
, and this top now serves as the bottom of the current stack frame.
But this creates an issue: if rbp
has been modified, what about the previous stack frame? Since the stack frame has been modified, after this function returns, rbp
would be in the wrong position and things would go very wrong.
This is where push rbp
comes in. It saves the value of rbp
before being modified so that right before the function returns, rbp
's original value can be popped right back to rbp
so the previous stack frame remains okay.
(Or in other words, rbp
is call-preserved, so we need to save/restore it as part of setting it up as a frame pointer for our stack frame.)