How does the stack work in assembly language?

Viewed 149553

I'm currently trying to understand how the stack works, so I've decided teach myself some assembly language, I'm using this book:

http://savannah.nongnu.org/projects/pgubook/

I'm using Gas and doing my development on Linux Mint.

I'm a bit confused by something:

As far as I was aware a stack is simply a data structure. So I assumed if I was coding in assembly I'd have to implement the stack myself. However this doesn't seem to be the case as there are commands like

pushl
popl

So when coding in assembly for the x86 architecture and using the Gas syntax: is the stack just a data structure that's already implemented? Or is it actually implemented at the hardware level? Or is it something else? Also would most assembly languages for other chip sets have the stack already implemented?

I know this is a bit of a foolish question but I'm actually quite confused by this.

17 Answers

I think primarily you're getting confused between a program's stack and any old stack.

A Stack

Is an abstract data structure which consists of information in a Last In First Out system. You put arbitrary objects onto the stack and then you take them off again, much like an in/out tray, the top item is always the one that is taken off and you always put on to the top.

A Programs Stack

Is a stack, it's a section of memory that is used during execution, it generally has a static size per program and frequently used to store function parameters. You push the parameters onto the stack when you call a function and the function either address the stack directly or pops off the variables from the stack.

A programs stack isn't generally hardware (though it's kept in memory so it can be argued as such), but the Stack Pointer which points to a current area of the Stack is generally a CPU register. This makes it a bit more flexible than a LIFO stack as you can change the point at which the stack is addressing.

You should read and make sure you understand the wikipedia article as it gives a good description of the Hardware Stack which is what you are dealing with.

There is also this tutorial which explains the stack in terms of the old 16bit registers but could be helpful and another one specifically about the stack.

From Nils Pipenbrinck:

It's worthy of note that some processors do not implement all of the instructions for accessing and manipulating the stack (push, pop, stack pointer, etc) but the x86 does because of it's frequency of use. In these situations if you wanted a stack you would have to implement it yourself (some MIPS and some ARM processors are created without stacks).

For example, in MIPs a push instruction would be implemented like:

addi $sp, $sp, -4  # Decrement stack pointer by 4  
sw   $t0, ($sp)   # Save $t0 to stack  

and a Pop instruction would look like:

lw   $t0, ($sp)   # Copy from stack to $t0  
addi $sp, $sp, 4   # Increment stack pointer by 4  

Regarding whether the stack is implemented in the hardware, this Wikipedia article might help.

Some processors families, such as the x86, have special instructions for manipulating the stack of the currently executing thread. Other processor families, including PowerPC and MIPS, do not have explicit stack support, but instead rely on convention and delegate stack management to the operating system's Application Binary Interface (ABI).

That article and the others it links to might be useful to get a feel for stack usage in processors.

You confuse an abstract stack and the hardware implemented stack. The latter is already implemented.

I think that main answer you are looking for has already been hinted at.

When an x86 computer boots up, the stack is not setup. The programmer must explicitly set it up at boot time. However, if you are already in an operating system, this has been taken care of. Below is a code sample from a simple bootstrap program.

First the data and stack segment registers are set, and then the stack pointer is set 0x4000 beyond that.


    movw    $BOOT_SEGMENT, %ax
    movw    %ax, %ds
    movw    %ax, %ss
    movw    $0x4000, %ax
    movw    %ax, %sp

After this code the stack may be used. Now I am sure it can be done in a number of different ways, but I think this should illustrate the idea.

The stack is just a way that programs and functions use memory.

The stack always confused me, so I made an illustration:

The stack is like stalactites

(svg version here)

  • A push "attaches a new stalactite to the ceiling".
  • A pop "pops off a stalactite".

Hope it's more helpful than confusing.

Feel free to use the SVG image (CC0 licensed).

The stack is "implemented" by means of the stack pointer, which (assuming x86 architecture here) points into the stack segment. Every time something is pushed on the stack (by means of pushl, call, or a similar stack opcode), it is written to the address the stack pointer points to, and the stack pointer decremented (stack is growing downwards, i.e. smaller addresses). When you pop something off the stack (popl, ret), the stack pointer is incremented and the value read off the stack.

In a user-space application, the stack is already set up for you when your application starts. In a kernel-space environment, you have to set up the stack segment and the stack pointer first...

The stack already exists, so you can assume that when writing your code. The stack contains the return addresses of the functions, the local variables and the variables which are passed between functions. There are also stack registers such as BP, SP (Stack Pointer) built-in that you can use, hence the built-in commands you have mentioned. If the stack wasn't already implemented, functions couldn't run, and code flow couldn't work.

I haven't seen the Gas assembler specifically, but in general the stack is "implemented" by maintaining a reference to the location in memory where the top of the stack resides. The memory location is stored in a register, which has different names for different architectures, but can be thought of as the stack pointer register.

The pop and push commands are implemented in most architectures for you by building upon micro instructions. However, some "Educational Architectures" require you implement them your self. Functionally, push would be implemented somewhat like this:

   load the address in the stack pointer register to a gen. purpose register x
   store data y at the location x
   increment stack pointer register by size of y

Also, some architectures store the last used memory address as the Stack Pointer. Some store the next available address.

The call stack is implemented by the x86 instruction set and the operating system.

Instructions like push and pop adjust the stack pointer while the operating system takes care of allocating memory as the stack grows for each thread.

The fact that the x86 stack "grows down" from higher to lower addresses make this architecture more susceptible to the buffer overflow attack.

You are correct that a stack is a data structure. Often, data structures (stacks included) you work with are abstract and exist as a representation in memory.

The stack you are working with in this case has a more material existence- it maps directly to real physical registers in the processor. As a data structure, stacks are FILO (first in, last out) structures that ensure data is removed in the reverse order it was entered. See the StackOverflow logo for a visual! ;)

You are working with the instruction stack. This is the stack of actual instructions you are feeding the processor.

You are correct that a stack is 'just' a data structure. Here, however, it refers to a hardware implemented stack used for a special purpose --"The Stack".

Many people have commented about hardware implemented stack versus the (software)stack data structure. I would like to add that there are three major stack structure types -

  1. A call stack -- Which is the one you are asking about! It stores function parameters and return address etc. Do read Chapter 4 ( All about 4th page i.e. page 53)functions in that book. There is a good explanation.
  2. A generic stack Which you might use in your program to do something special...
  3. A generic hardware stack
    I am not sure about this, but I remember reading somewhere that there is a general purpose hardware implemented stack available in some architectures. If anyone knows whether this is correct, please do comment.

The first thing to know is the architecture you are programming for, which the book explains (I just looked it up --link). To really understand things, I suggest that you learn about the memory, addressing, registers and architecture of x86 (I assume thats what you are learning --from the book).

I was searching about how stack works in terms of function and i found this blog its awesome and its explain concept of stack from scratch and how stack store value in stack.

Now on your answer . I will explain with python but you will get good idea how stack works in any language.

enter image description here

Its a program :

def hello(x):
    if x==1:
        return "op"
    else:
        u=1
        e=12
        s=hello(x-1)
        e+=1
        print(s)
        print(x)
        u+=1
    return e

hello(3)

enter image description here

enter image description here

Source : Cryptroix

some of its topic which it cover in blog:

How Function work ?
Calling a Function
 Functions In a Stack
 What is Return Address
 Stack
Stack Frame
Call Stack
Frame Pointer (FP) or Base Pointer (BP)
Stack Pointer (SP)
Allocation stack and deallocation of stack
StackoverFlow
What is Heap?

But its explain with python language so if you want you can take a look.

Related