Wednesday, October 6, 2010

C calling conventaion && active record && stack

The fast way to understand C calling convention is to write a C program and compile it into assembly, and understand the assembly code. For exmaple:
## test.c ##
#include <stdio.h>
int sum(int a, int b)
{
  int c;
  c= a+b;
  return c;


}
int main(void)
{
  int a = 1;
  int b = 2;
  sum(a, b);
  return 1;
}




## compile ##
gcc -S test.c


## assembly ##
    .file    "test.c"
    .text
.globl sum
    .type    sum, @function
sum:
    pushl    %ebp                             // save previous ebp, which is ebp in main()
    movl    %esp, %ebp                   // set the new ebp of sum() = current esp value
    subl    $16, %esp                       // esp = esp -16
    movl    12(%ebp), %eax            // *(%ebp+12), this is value b, put in eax
    movl    8(%ebp), %edx              // put value a into edx
    leal    (%edx,%eax), %eax        //
    movl    %eax, -4(%ebp)             //*(ebp-4): this is local variable c.
    movl    -4(%ebp), %eax            // put c into eax again, becase return value in eax
    leave                                       // movl %ebp, %esp; pop %ebp
                                                   // set the value of esp = the value of ebp, pop the 
                                                   // first element in stack, which is the saved ebp    ret                                        // pop %eip, pop the return address, and save to eip
    .size    sum, .-sum
.globl main
    .type    main, @function
main:
    pushl    %ebp                           // save ebp
    movl    %esp, %ebp                 // the value in ebp reigster = the value in esp reg
    subl    $24, %esp                     // esp = esp -24


/*push the local variables into stack*/
    movl    $1, -4(%ebp)                // put value 1 into stack. this is local variable.
                                                    // ebp always point to the top of local variables
    movl    $2, -8(%ebp)                // put value 2 into stack, (int b)


/*push the paramters of sum function into statck*/
/*remember, C convention push the last parameter into stack first*/
    movl    -8(%ebp), %eax           // value of eax = content of ((value of ebp) - 8)
                                                   // integers are 4 bytes. This is "int b"
    movl    %eax, 4(%esp)            // content of ((value of esp)+4) = value of eax
    movl    -4(%ebp), %eax          // this is "int a" of sum() parameters
    movl    %eax, (%esp)             // even we assignment two paramaters on the
                                                  // stack, but we didn't change the value of esp
                                                  // "push", "pop", "call", ret" instructions change esp
/*start to call subprogram*/
    call    sum                             // push %eip;  movl sum, %eip
                                                 // this will save the return address of sum()




/*end this function*/
    movl    $1, %eax                   // put 1 into eax, this is the return value.
    leave                                     // movl %ebp, %esp; pop %ebp
                                                 // set the value of esp = the value of ebp, pop the 
                                                 // first element in stack, which is the saved ebp
    ret                                        // pop %eip, pop the return address, and save to eip


    .size    main, .-main
    .ident    "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits










In active record, the sequence is:


..................4G......................


parameter n
parameter n-1
paremeter 1
Return address
previous ebp ______________current ebp point to here(betwen "perv ebp" & v1)
local variable1
local vraible2


.................. 0 .......................


esp suppose point to the top of stack. instrunction like push pop will change esp automatically. some other instruction like call, ret which include "push" or "pop" could also change esp.

No comments: