Stack / base pointers in assembly
This actually depends upon not only the hardware architecture and the compiler, but also the calling convention, which is simply an agreed-upon way in which functions work with the stack to call one another. In other words, there are different orders in which a function can push things onto the stack, depending on your compiler settings (and peculiar #pragma
options, etc, etc).
It looks like you are talking about the cdecl
calling convention on the x86 architecture. In that case, the caller's ebp
is usually pushed onto the stack immediately after the return address. So, in your example's N-2, location 25 will contain a pointer back to the calling function N-3 (ie, it will contain the address of the instruction immediately after the call
that got you into N-2) and location 24 will contain the old ebp
, and your esp will = 23 immediately after the call, before any locals have been pushed onto stack. (Except some compilers will make space on the stack immediately after the call, and so ESP will be 20 instead of moving up and down inside function N-2.)
However be aware that on the x86 there is a particular optimization the compiler can sometimes do called frame pointer omission, which avoids pushing the old ebp
onto the stack altogether under certain conditions.
- After calling into
N-3
,ebp
is28
, andesp
is25
. - The old
ebp
is pushed, and then theebp
is set to the current value ofesp
. Now bothesp
andebp
are24
. - Finally,
esp
is adjusted to make room for local variables.esp
is likely now20
, depending on how the function behaves when callingN-2
.
The best way to get your head around this, is read about function prologues, and familiarize yourself with the x86 implementation. It also helps to accept that esp
and ebp
are used to localize use of the stack in each function, with some variation between compilers, architectures and platforms (and almost irrelevant to the user of any language higher level than, or equal to C).