Based on this Stack Overflow answer and this Stack Exchange answer
Just like cmp
and jl
, the call
and ret
instructions accomplish many tasks using a single instruction so it’s a bit hard to see what they are doing (if you don’t know about it already). If you take a look at the cdecl calling convention for Intel x86, it says just that a new function will first push the content of ebp onto the stack and pop it back to ebp when it’s done to restore it, like
But what about eip? It’s mentioned from time to time that call
and ret
will handle eip automatically and eip will just jump around accordingly, but how? According to what is mentioned in the two pages I have listed above, as it turns out, the caller’s stack frame should instead be like
Just like what’s mentioned here (p. 5), here, and here (p. 16), the call
instruction will push eip onto the stack before it jumps elsewhere and the ret
will simply do a pop eip
. And that also explains why functions (when the stack grows downwards) will usually fetch 4(%esp)
(instead of (%esp)
) for its first argument.
Related details can also be found from this page.