Search code examples
assemblyx86nasmstack-pointer

Base pointer and stack pointer


Given this piece of code:

       swap:

            push ebp ; back up the base pointer,
            mov ebp, esp
            ; push the context of the registers on the stack

            push eax
            push ebx
            push ecx
            push edx

            mov eax, [ebp+8] ; address of the first parameter
            mov ebx, [ebp+12] ; address of the second parameter
            mov dl, [eax]
            mov cl, [ebx]

            mov [eax], cl

            mov [ebx], dl

            ; restore the context of the registers from the stack

            pop edx
            pop ecx  
            pop ebx
            pop eax
            ; restore the ebp
            pop ebp
            ret

(This is just the method. Previously we pushed the first and the second parameter on the stack.)

My question is: why do we add 8 to the Base Pointer to get to the address of the first parameter and then 12 ?

I get the fact that they are dword so each of them are 4 bytes..so from ebp + 8 to ebp + 12 it makes sens to make. But why the first one is ebp + 8 ? Because if ESP points to the TOP of the stack, mov ebp, esp means that EBP points to the TOP of the stack. Then we push 4 values on the stack : eax, ebx, ecx and edx. Why is EBP + 8 pointing on the first parameter ?


Solution

  • When the function is called, the stack looks like:

    +-------------+
    | Parameter 2 |
    +-------------+
    | Parameter 1 |
    +-------------+
    | Return Addr |  <-- esp
    +-------------+    
    

    then after the "stack frame" is set up:

    +-------------+
    | Parameter 2 | <-- [ebp + 12]
    +-------------+
    | Parameter 1 | <-- [ebp + 8]
    +-------------+
    | Return Addr |  
    +-------------+    
    | saved ebp   | <-- ebp
    +-------------+ <-- esp
    

    Now the context is saved:

    +-------------+
    | Parameter 2 | <-- [ebp + 12]
    +-------------+
    | Parameter 1 | <-- [ebp + 8]
    +-------------+
    | Return Addr |  
    +-------------+    
    | saved ebp   | <-- ebp
    +-------------+ 
    | saved eax   |  
    +-------------+    
    | saved ebx   |  
    +-------------+    
    | saved ecx   |  
    +-------------+    
    | saved edx   | <-- esp
    +-------------+    
    

    Don't forget that on many systems the stack grows downward (and that is definitely true of the x86 family), so the top of the stack will have the lowest memory address.