Search code examples
cassemblyx8632-bit

C assembly language ATT walkthrough?


I have a simple c program that multiplies and adds three variables and returns the results. I have compiled the code into assembly language (ATT format) on a 32 bit machine. I am trying to learn assembly code, and while I can understand some of the lines, I need help understanding why for example leal (%edx, %edx, 2), %edx, would be done in the following code, like what would be the result to that, what would it accomplish?

Assembly code

.file   "calc.c"
        .text
.globl calc
        .type   calc, @function
calc:
        pushl   %ebp                   #prolog
        movl    %esp, %ebp             #prolog
        movl    8(%ebp), %edx          #move %ebp +8 into %edx 
        movl    16(%ebp), %ecx         #move %ebp +16 into %ecx
        leal    (%edx,%edx,2), %edx
        movl    12(%ebp), %eax
        leal    (%edx,%eax,2), %eax
        movl    %ecx, %edx
        sall    $4, %edx
        subl    %ecx, %edx
        addl    %edx, %eax
        popl    %ebp
        ret
        .size   calc, .-calc
        .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits

C program

#include <stdio.h>
int calc(int x, int y, int z){
    return 3*x + 2*y + 15*z;
}
int main(void) {
    int x = 2;
    int y = 6;
    int z = 11;

    int result = calc(x,y,z);

    printf("x=%d, y=%d, z=%d, result=%d\n", x,y,z,result);
    return 0;
}

Could someone help me trace the problem starting from the prolog.


Solution

  • Maybe it can be best explained with the C function code in mind:

    int calc(int x, int y, int z){
        return 3*x + 2*y + 15*z;
    }
    

    Look at parameter x. It is multiplied by 3 so it is easily recognizable in the assembly code:

    movl    8(%ebp), %edx
    

    ....

    leal    (%edx,%edx,2), %edx
    movl    12(%ebp), %eax
    leal    (%edx,%eax,2), %eax
    

    It moves the value of argument x into edx. The address of argument x in the stack frame is ebp+8. Then later on with leal it adds edx to 2*edx and stores the value in edx. That equals 3*x.
    Then loads argument y into eax, wich you can recognize easily because y is a 32bit int so it is 4 bytes past the start address of x.
    Next leal adds edx (i.e. 3*x) with 2*eax (i.e. 2*y) and stores the result in eax, thus in eax you have 3*x + 2*y.
    And so on...