I am currently learning the basics of assembly and came across something odd when looking at the instructions generated by GCC(6.1.1).
Here is the source:
#include <stdio.h>
int foo(int x, int y){
    return x*y;
}
int main(){
    int a = 5;
    int b = foo(a, 0xF00D);
    printf("0x%X\n", b);
    return 0;
}
Command used to compile: gcc -m32 -g test.c -o test
When examining the functions in GDB I get this:
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x080483f7 <+0>:     lea    ecx,[esp+0x4]
   0x080483fb <+4>:     and    esp,0xfffffff0
   0x080483fe <+7>:     push   DWORD PTR [ecx-0x4]
   0x08048401 <+10>:    push   ebp
   0x08048402 <+11>:    mov    ebp,esp
   0x08048404 <+13>:    push   ecx
   0x08048405 <+14>:    sub    esp,0x14
   0x08048408 <+17>:    mov    DWORD PTR [ebp-0xc],0x5
   0x0804840f <+24>:    push   0xf00d
   0x08048414 <+29>:    push   DWORD PTR [ebp-0xc]
   0x08048417 <+32>:    call   0x80483eb <foo>
   0x0804841c <+37>:    add    esp,0x8
   0x0804841f <+40>:    mov    DWORD PTR [ebp-0x10],eax
   0x08048422 <+43>:    sub    esp,0x8
   0x08048425 <+46>:    push   DWORD PTR [ebp-0x10]
   0x08048428 <+49>:    push   0x80484d0
   0x0804842d <+54>:    call   0x80482c0 <printf@plt>
   0x08048432 <+59>:    add    esp,0x10
   0x08048435 <+62>:    mov    eax,0x0
   0x0804843a <+67>:    mov    ecx,DWORD PTR [ebp-0x4]
   0x0804843d <+70>:    leave  
   0x0804843e <+71>:    lea    esp,[ecx-0x4]
   0x08048441 <+74>:    ret    
End of assembler dump.
(gdb) disas foo
Dump of assembler code for function foo:
   0x080483eb <+0>:     push   ebp
   0x080483ec <+1>:     mov    ebp,esp
   0x080483ee <+3>:     mov    eax,DWORD PTR [ebp+0x8]
   0x080483f1 <+6>:     imul   eax,DWORD PTR [ebp+0xc]
   0x080483f5 <+10>:    pop    ebp
   0x080483f6 <+11>:    ret    
End of assembler dump.
The part that confuses me is what it is trying to do with the stack. From my understanding this is what it does:
- It takes a reference to some memory address 4 bytes higher in the stack which from my knowledge should be the variables passed to main since espcurrently pointed to the return address in memory.
- It aligns the stack to a 0 boundary for performance reasons.
- It pushes onto the new stack area ecx+4which should translate to pushing the address we are suppose to be returning to on the stack.
- It pushes the old frame pointer onto the stack and sets up the new one.
- It pushes ecx(which is still pointing to would should be an argument tomain) onto the stack.
Then the program does what it should and begins the process of returning:
- It restores ecxby using a-0x4offset onebpwhich should access the first local variable.
- It executes the leave instruction which really just sets esptoebpand then popsebpfrom the stack.
So now the next thing on the stack is the return address and the esp and ebp registers should be back to what they need to be to return right?
Well evidently not because the next thing it does is load esp with ecx-0x4 which since ecx is still pointing to that variable passed to main should put it at the address of return address on the stack.
This works just fine but raises the question: why did it bother to put the return address onto the stack in step 3 since it returned the stack to the original position at the end just before actually returning from the function?
 
     
    