What's the difference between sub $0x8, %rsp and push %rbx at function entry?
Both move %rsp down by 8 bytes, but push %rbx also saves the register's value — the compiler picks push when it actually needs that callee-saved register, and sub $8 when it just needs padding.
* Both restore 16-byte alignment by moving rsp down 8; push does double duty and also saves the register's value. *
Both instructions exist mainly to fix the same problem: stack alignment. When a function uses %rbx (a callee-saved register it must preserve), push %rbx does double duty — it stashes the old value AND nudges the stack by 8 bytes. When the function uses no callee-saved registers but still needs alignment, the compiler emits a bare sub $8, %rsp, which adds 8 bytes of dead padding and saves nothing.
Why alignment matters: The System V ABI requires %rsp to be 16-byte aligned right before any call. But call itself pushes the 8-byte return address, so on entry the stack is misaligned by 8. A single push (or sub $8) restores the 16-byte alignment so the function can safely call others.
Quick check: Count push instructions in the prologue. If there's an odd number, the stack is aligned. If even, look for an extra sub $8, %rsp.
Go deeper: