Mar 14, 2011

Anatomy of a process stack

A process is a program in execution. A process may have one or more threads executing different sections of the program. Every thread in the process maintains it's own separate stack, registers and program counter.

Key Points
A stack is a collection of stack frames where each stack frame refers to a function call

Stack Frame
When a function call is made, a block of memory is set aside which stores information about the following:
1. Arguments passed to the function
2. Return address of the caller function
3. Local variables used by the function and
4. Other temporary variables needed by the compiler
This block of memory is called a stack frame. When the function returns, the stack frame is turned invalid and reclaimed.

Registers used in a Stack Frame
1. ESP (Extended Stack Pointer) : 32 bit register that points to the top of the stack. All the addresses lower than the stack pointer are considered unused or garbage and all the higher addresses are considered valid
2. EBP (Extended Base Pointer) : Also known as Frame Pointer, this 32 bit register is used to reference all the function parameters and the local variables in the current stack frame

ebp + 4 + 4 * n points to the address at which the nth argument of the function is stored
ebp + 4 points to the address at which return address of the caller function is stored
ebp is the frame pointer of the callee function
ebp - 4n refers to the address where the nth local variable is stored

3. EIP (Extended Instruction Pointer) : This register holds the address of the next instruction to be executed. It is saved on to the stack as part of the CALL instruction. Also known as Program Counter
4. EAX, EBX, ECX, EDX : General purpose registers for storing intermediate results

Following figure shows how stack frames are laid out in memory during execution


Mechanism of a function call
1. The parameters passed to the function are pushed on to the stack from right to left
2. The function is called using the CALL instruction. After this call, the callee function takes control of the proceedings
3. The callee function saves the current value of the Base Pointer and updates it to the value of the stack pointer (top of the stack).

push ebp         # saves the current value of base pointer
mov  ebp, esp    # updates the base pointer value with the value of the stack pointer

4. The callee function may save the values in CPU registers and allocate space for local variables
5. Before returning, the function must clean up the local variables, restore stack registers with old values, restore the old base pointer (ebp) and return from the function using the RET instruction

The assembler code file of the following code sample explains few of the points mentioned above

C Program
int add(int x, int y)
{
    int rc;
    rc = x + y;
    return rc;
}

int main()
{
    int rc = 0;
    rc = add(4, 8);
}

GCC Assembler Code of the above program: Command Used gcc -S -masm=intel -fverbose-asm main.c
.file   "main.c"
    .intel_syntax
    .text            # start of the text section or code
.globl _add          # defines the _add symbol as global, making it visible to the linker and outside
    .def    _add;   .scl    2;  .type   32; .endef

_add:
    push    ebp      #  Save main function's base pointer
    mov ebp, esp     #  Update base pointer with current value of stack pointer (top of the stack)
    mov eax, DWORD PTR [ebp+12]  # y, y  
    add eax, DWORD PTR [ebp+8]   # y, x
    pop ebp  #
    ret
    .def    ___main;    .scl    2;  .type   32; .endef
.globl _main

    .def    _main;  .scl    2;  .type   32; .endef
_main:
    push    ebp      #
    mov ebp, esp     #
    call    ___main  # calls the ___main function which will do the start-up initialization
    push    8        # push the parameters on the stack from right
    push    4        # 
    call    _add     # call the add function
    pop eax  #
    pop edx  #
    leave
    ret

References:
Codeguru
Unixwiz
Citizendium
How function calls work
Understanding the Stack
Osdev Wiki
GDB tutorial

2 comments :

Soma Sekhar said...

HI ,

You said that "The parameters passed to the function are pushed on to the stack from right to left" , but in the picture , for funcB , the arguments passed are m and n in the order , but if the arguments are taken from right to left , should it not be n an m ? as the funcB is declared as funcB(int m , int n).

pankaj said...

@Soma Sekhar

Nice Catch! The picture needs to be corrected. Thanks for bringing that up!

Post a Comment