In terms of x86 assembly code anyways. I've been reading about function calls, but still can't fully grasp the need for a base / frame pointer (EBP) along with a stack pointer (ESP).
When we call a function, the current value of EBP will be placed on the stack and then EBP gets the current ESP value.
Place holders for the return value, function arguments and local variables of the function will then be placed on the stack, and the stack pointer ESP value will decrease (or increase) to point to after the last placeholder placed on the stack.
Now we have the EBP pointing to the beginning of the current stack frame, and ESP pointing to the end of the stack frame.
The EBP will be used to access the arguments and local variables of the function due to constant offsets from the EBP. That is fine. What I don't understand is, why can't the ESP just be used to access these variables also by using its offsets. The EBP points to the beginning of the stack frame , and the ESP points to the end of the stack frame. What's the difference?
The ESP shouldn't change from once there has been a placeholder for all the local variables etc. or should it?
-fomit-frame-pointer
. – Attemperpush
in compiler-generated code to pass function args. But yes, clang with-Oz
(optimize for code-size even at the expense of speed) will use stuff likepush 2
/pop rcx
(3 bytes total) instead of 5-bytemov ecx, 2
. push/pop instead ofmov reg,reg
is insane, though. It only saves 1 byte for 64-bit regs that aren't r8..r15, otherwise it's break even or a loss. (3-bytemov r8, r9
vs. 2-bytepush r9
+ 2-bytepop r8
.) In 32-bit code, 2-bytemov
is always better thanpush
/pop
for speed and break-even for size. – Creamy