Talk:X86 Disassembly/Functions and Stack Frames

Using esp for automatic variables?
Actually, I would think that programs use ebp for automatic variables, because if esp is used, the offset used will keep on changing as you push and pop things. For example:

push ebp mov ebp, esp sub esp, 4 mov dword [esp+0], 123 ; using our variable push 321 mov eax, [esp+4] ; we have to use 4 as an offset, because [esp+0] contains 321. push 432 ; and now the offset to the variable is 8 add esp, 8 ; offset is back to 0 mov esp, ebp pop ebp ret

However, I could use [ebp-4] as long as I like to reference the variable.

Wj32 10:22, 8 January 2007 (UTC)
 * My experience looking at compiled code under the debugger would seem to bear this out; auto variables are always referenced as offset from ebp for exactly this reason.

EBP is not needed for execution at all, if other information is pushed and popped, the compiler can still calculate the location of the local variables based entirely on esp (it just needs to keep track of how the stack is modified). The real explanation of why ebp is used can be found here http://blogs.msdn.com/larryosterman/archive/2007/03/12/fpo.aspx, here http://www.nynaeve.net/?p=91 and here http://mituzas.lt/2009/07/26/on-binaries-and-fomit-frame-pointer/. Actually, gcc has a flag to avoid generation stack frames, -fomit-frame-pointer, but may hinder the later obtention of backtraces in x86 --213.37.221.151 (talk) 03:20, 5 January 2010 (UTC)


 * One thing never mentioned in the article is that in modern compilers, not even is the order of declarations of auto variables not mirrored in their allocation on the stack, a specific offset from ebp may, at some times, be one auto variable, sometimes another... and some auto variables are always in registers, never appearing on the stack at all. Chazz (talk) 07:42, 17 May 2009 (UTC)

Isn't EBP-4 the first local variable?
the tutorial uses to explain
 * a = [ebp - 12] = [esp], b = [ebp - 8] = [esp + 4], c = [ebp - 4] = [esp + 8]
 * int a,b,c;

Wouldn't it be though, seeing that right there at the "crude" graphical representation of a stack it says that the first local variable is at ebp - 4? Nothingist (talk) 07:54, 28 August 2009 (UTC)
 * a = [ebp - 4] = [esp], b = [ebp - 8] = [esp + 4], c = [ebp - 12] = [esp + 8]
 * this page appears to backup this up, that ebp-4 = 1st local parameter, ebp-8 = 2nd local parameter:
 * http://www.cs.uaf.edu/2008/fall/cs301/support/x86/index.html

C and Pascal calls -- differences
HI, There are 2 things not mentionned here : 1- in C you push parameters from right to left and the caller is supposed to restore the stack 2- if you use pascal (or WINAPI) style, parameters are push from left to right and the callee restores the stack (that's what Microsoft says)

So, a standard C function call MyFunction(10, 5, 2); will create this code push 2 push 5 push 10 call MyFunction add esp, 12

And MyFunction should be  push ebp mov ebp, esp sub esp, nn ; local variables ...  mov esp, ebp pop ebp ret ; or ret 0

if MyFunction2 is declared as _pascal (or __pascal or WINAPI ...) _pascal MyFunction(10, 5, 2); will create this code push 10 push 5 push 2 call _MyFunction@12 ; C compiler add @12 because 12 bytes are pushed

And _MyFunction@12 should be  push ebp mov ebp, esp sub esp, nn ; local variables ...  mov esp, ebp pop ebp ret 12; pop the three parameters

Pushing parameters from right to left lets you use '...' in functions parameters ( ex: printf(const char *format, ...); ). You can't do that in Pascal ! The pascal form generates a smaller code (only one 'ret nn', instead of an 'add esp, nn' on each call) and you can control parameters.

ps. Don't hesitate to correct my spelling ;)

Standard Exit Sequence (possibly word duplicated)
From reading the first section of the exit sequence, see bold text below:

The Standard Exit Sequence must undo the things that the Standard Entry Sequence does. To this effect, the Standard Exit Sequence must perform the following tasks, in the following order:

Remove space for local variables, by reverting esp to its old value. Restore the old value of ebp to its old value, which is on top of the stack. Return to the calling function with a ret command.

To me, it appears that the "old value" is unnessecary written twice? Compare to the below: (my suggested correction)

Restore ebp to its old value, which is on top of the stack.

Olof nord (discuss • contribs) 12:12, 2 November 2014 (UTC)