Look at gcc output. It defaults to -fomit-frame-pointer
when optimizing, only making a stack frame when functions use variable-length arrays or it needs to align the stack to more than 16B.
That wiki page is basically wrong. There's no scary weird stuff that makes it "unreliable". The only time you can't do it is when you need to modify RSP by an amount that isn't an assemble-time constant.
However, if you do make a stack frame with push rbp
/ mov rbp, rsp
, you should use RBP-relative addressing modes. It's more efficient, because [rsp + 8]
takes an extra byte to encode (vs. [rbp - 8]
). Addressing modes with RSP as the base register always need a SIB byte, even when there's no index register.
The point of using RSP-relative addressing modes is that you can avoid wasting instructions making a stack frame, so RBP is just another call-saved register (like RBX) that you can save/restore and use for whatever you want.
The other big advantage to RBP-relative addressing is that the offset from RBP to a given variable stays constant for the entire function. Unlike compilers, we puny humans are easily confused by pushes and pops which change RSP inside a function. Of course, 64-bit code hardly ever changes RSP inside a function between the prologue and epilogue, because both ABIs pass args in registers. Saving/restoring some call-preserved registers (like RBX or R12-R15) in the prologue/epilogue is often better than having push/pop inside the function (and definitely better than inside a loop). When you need to spill/reload, mov
for random access is usually best.
In 32-bit code, making a stack frame in hand-written code often makes more sense, esp. for maintainability. In 64-bit code, it's usually not much of an issue. Although saving/restoring an extra register with an extra pair of push/pop does change the stack layout, which does matter if any args were passed on the stack (e.g. a large struct by value, but write your function to take a const-pointer arg instead!).
alloca()
, using offsets from the stack pointer may no longer be possible. – EOF