Where the top of the stack is on x86

February 4th, 2011 at 7:24 am



The stack analogy



Hardware stacks


The stack in x86





Pushing and popping data with the stack pointer





push eax

Is actually equivalent to this:

sub esp, 4
mov [esp], eax




pop eax

Is equivalent to this:

mov eax, [esp]
add esp, 4




Stack frames and calling conventions


I’ll demonstrate this with a simple C program:

int foobar(int a, int b, int c)
    int xx = a + 2;
    int yy = b + 3;
    int zz = c + 4;
    int sum = xx + yy + zz;

    return xx * yy * zz + sum;

int main()
    return foobar(77, 88, 99);




Compiled with gcc into assembly as follows:

gcc -masm=intel -S z.c -o z.s


    ; ebp must be preserved across calls. Since
    ; this function modifies it, it must be
    ; saved.
    push    ebp

    ; From now on, ebp points to the current stack
    ; frame of the function
    mov     ebp, esp

    ; Make space on the stack for local variables
    sub     esp, 16

    mov     eax, DWORD PTR [ebp+8]
    add     eax, 2
    mov     DWORD PTR [ebp-4], eax

    mov     eax, DWORD PTR [ebp+12]
    add     eax, 3
    mov     DWORD PTR [ebp-8], eax

    mov     eax, DWORD PTR [ebp+16]
    add     eax, 4
    mov     DWORD PTR [ebp-12], eax

    ; add xx + yy + zz and store it in sum
    mov     eax, DWORD PTR [ebp-8]
    mov     edx, DWORD PTR [ebp-4]
    lea     eax, [edx+eax]
    add     eax, DWORD PTR [ebp-12]
    mov     DWORD PTR [ebp-16], eax

    ; Compute final result into eax, which
    ; stays there until return
    mov     eax, DWORD PTR [ebp-4]
    imul    eax, DWORD PTR [ebp-8]
    imul    eax, DWORD PTR [ebp-12]
    add     eax, DWORD PTR [ebp-16]

    ; The leave instruction here is equivalent to:
    ;   mov esp, ebp
    ;   pop ebp
    ; Which cleans the allocated locals and restores
    ; ebp.



Related posts:

  1. Stack frame layout on x86-64
  2. Position Independent Code (PIC) in shared libraries on x64
  3. when bit endianness matters
  4. Position Independent Code (PIC) in shared libraries
  5. Load-time relocation of shared libraries

28 Responses to “Where the top of the stack is on x86”

  1. Iouri GoussevNo Gravatar Says:

    Thanks, I love learning how software works at low-level.

  2. Michael AyeNo Gravatar Says:

    As this is published on Planet Python, why not put a nice example in here how to simulate a stack with a list? Not sure what the agreement officially is, but I was just a bit puzzled to find a post on the Planet Python feed that not once mentions Python.
    Otherwise, good information, thanks!

  3. elibenNo Gravatar Says:


    I also don’t know what the “agreement” officially is with Planet Python, but there are quite a few non-Python related articles out there. For my blog, I think they’re aggregating the programming category which includes Python, but also my other posts on programming. I’m sorry if it disturbs you.

  4. Kent JohnsonNo Gravatar Says:

    This is not special to x86, this is the way the stack works on every architecture I am familiar with.

  5. Joe BrandtNo Gravatar Says:

    Things get more interesting if you add some erroneous code:

    memset(&y, 0, sizeof(y) * 4); // zeros 16 bytes

    What happens? Well y is zeroed, but the value of x, the stored ebp and return address are also trashed. This is the source of many bugs and security exploits.
    So its important to note that although the stack grows toward low addresses, arrays and their elements go from low to high addresses.

  6. elibenNo Gravatar Says:


    I agree. I was focusing on x86 here but the same may be said about many other architectures.


    Indeed, and not terminating local buffers properly will allow attackers to overwrite the function return address, jumping to their malicious code. Regarding the extra notice, this article assumes some non-basic level of programming understanding. I’m hope understanding where array indices grow is included in that understanding :-)

  7. IgnatiusNo Gravatar Says:

    This subject material should be familiar with someone who went through a formalized computer science core in the ’90s, however that being said, it seems many young developers have come from other fields, or the approach to CS has changed such that these fundamentals are no longer favored.

    The care and attention to detail so common throughout your articles, displayed in your use of informative illustrations, code snippets and generously sprinkled with warnings of common pitfalls/misconceptions, is a service to the community. Further, I can not detect ego or hubris, but only a desire to share with others your hard won information, for this I wanted to express my thanks.

  8. Eversor1No Gravatar Says:

    Your article admits that the association “may be confusing to some people”. I suggest that it may be confusing to all people because the words top and bottom do not correctly explain what they are representing in your explanation, and are frankly misused. Instead of trying to alter the dictionary definition of “top” and “bottom” why not just change the terminology as applied to the stack? This seems to be a simple enough solution. Your pushes and pops affect the bottom of the stack.

  9. elibenNo Gravatar Says:


    Thanks for the kind words :-)


    The dictionary is hardly relevant here. Wishful thinking about changing the terminology as applied to the stack can be a pleasant thought exercise, but in the end of the day you open Intel’s x86 programmer’s manual, and read on the push instruction (emphasis is mine):

    Decrements the stack pointer and then stores the source operand on the top of the stack.

    My intention in this article is just to clarify things and I freely admit there’s a confusion in the terminology.

  10. JasonNo Gravatar Says:

    Thank you. I don’t have a formal programming education and my head has always hurt when working in languages where I have to manipulate data on the stack directly. You’re elegant post has set my head straight (upside down) and I can now fully visualize what is happening and suspect I won’t have future headaches. Thank you again!

  11. jkNo Gravatar Says:

    Great article! :-)


    I think its all about perspective anyway. For example, I think of memory in the opposite way that is illustrated here such that the lower addresses are shown at the top of the page (rotate these diagrams 180 degrees). In this case the “high” and “low” refers to the numbering of the addresses and not their position on the page. This is how disassemblers typically show sections of memory as well. Conveniently, this view also makes the whole top and bottom thing intuitive.

  12. Phil MayesNo Gravatar Says:


    But every core dump ever printed was in this format. After a while, you become directionally agnostic (bidirectional??).

  13. Nicolas DumazetNo Gravatar Says:

    Amazing, I came here from Planet Python, and I’m happy that some “off-topic” non-Python posts pop up from time to time. I wasn’t educated in the 90′s, but it has been at least 5 years since I last worked with some registers. It’s good to freshen up a bit!

  14. frankNo Gravatar Says:

    Thanks a lot i never understand in deep the stack.. so thanks a lot

  15. frankNo Gravatar Says:

    ehm.. as Phil Mayes wrote seems that there is a error..about high address and low address in the last diagram? is it? then where is located the return foobar? is it located at EBP+4(return adress)?

  16. le kommieNo Gravatar Says:

    When compiling the example on 64-bit Linux (GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2″), use the following command line to compile into assembler:

    gcc -masm=intel -march=i386 -m32 -S z.c -o z.m

    Not using -march and -m32 will produce a completely different output.

  17. elibenNo Gravatar Says:

    le kommie,

    Good point. I was compiling this on a 32-bit Ubuntu. To compile 32-bit objects on 64-bit Ubuntu, indeed some special flags have to be passed.

  18. candidoNo Gravatar Says:


    a very good webblog. I am primer with C and assembly programming, level of these 3 references ( –C programming: a Modern Aproach, –A Computer System: A programmers perspective, –Introduction to Computer Organizationwith x86-64 Assembly language & GNU/Linux) and for stack research I just begin studing with the topic: shellcode injected in stack of a vulnerable program STACK OVERWRITING and the problem is that i am searching for a good book or reference about this topic and i have not had succeeded. The reference Shellcode Handbook is out of date and today SO have a lot of security ( stack bound check, canarys, non executable, stack, etc ….), so for a track of book examples I need updated it and me conclusion is that i need today linux kernel security concepts background. I can see that you are expert on unix environment, so, I would like know some update reference about that. My plaform is linux/GNU, ubuntu10.04 distribution 32 bits arch and toolbox (GNU emacs, gcc 4.4.3, gdb 6.8)

    Thanks in advance
    Cándido Aramburu
    Universidad Publica de Navarra

  19. elibenNo Gravatar Says:


    I’m not familiar with books on this topic

  20. MattNo Gravatar Says:

    Just wanted to say thanks. Your straightforward explanation cleared up a lot of my confusion regarding the stack frame. It has been an excellent supplement to my OS class.

  21. vaibhavNo Gravatar Says:

    Thanks a lot for such a wonderful article :)
    Keep writing!

  22. SreeNo Gravatar Says:

    ‘Can anyone tell me how to find the starting address of stack and heap?’
    ‘Also i want information about how to find where the stack and heap overlaps?’

  23. geek42No Gravatar Says:

    1, the stack concept are explained brief in CSAPP( i read the CSAPP2e)

    2, the order is follow the endian order , this might be the keypoint, but the enture of position of BOS might could limit the memory usage, just a personal opinion

  24. LeonNo Gravatar Says:

    Just use diagrams that have lower addresses on the top and the whole article becomes obsolete.

  25. elibenNo Gravatar Says:


    And yet, many resources prefer to keep the “top” actually on top. If you draw the low addresses on top, then the concept of “above” and “below” becomes inverted and confusing.

    Let’s say I want to describe where locals are. I say “they are below ebp”. With the diagrams as shown in this post, this makes sense visually. Invert them, though, and it will stop making sense.

    So things are not so simple, I think.

  26. NimeshNo Gravatar Says:

    Thanks! This site is the best.

  27. jucestainNo Gravatar Says:

    Great article; great website! Appreciate the time and effort you spent writing these up.

  28. Dongseon LeeNo Gravatar Says:

    Thanks a lot. I havn’t found any information about the stack structure except your article. It’s great and precise.

Leave a Reply
