Is my understanding of this assembly correct?

Viewed 81

The source is in C, and I compiled it using gcc 11.1 with optimizations disabled (-O0). The link to the assembly is here so you may see it for yourself.

I've annotated the assembly with what I think is happening and "??" for lines I'm not too sure about.

For now, I'm only concerned with main() and someAlgebra(), and so, I've noted only these bits in the assembly listing.

C source

#include <stdio.h>

const char *MY_LIST[] = {
    "of",
    "the",
    "four",
    "green",
    "houses",
    "one",
    "hides",
    "five",
    "amazing",
    "secrets"
};


int someAlgebra(int x, int y)
{
    int a = 4;
    int b = 3;
    return 2*x + 3*y + a - b;
}


void printAll(const char *the_list[], unsigned length)
{
    for(unsigned i = 0; i < length; i++) {
        puts(the_list[i]);
    }
}




int main(int argc, char *argv[])
{
    int k = someAlgebra(3, 5);
    // printf("Size of [int] (bytes): %u\n", sizeof(int));
    // printf("Size of [int *] (bytes): %u\n", sizeof(int *));
    return 0;
}

Assembly

.LC0:
        .string "of"
.LC1:
        .string "the"
.LC2:
        .string "four"
.LC3:
        .string "green"
.LC4:
        .string "houses"
.LC5:
        .string "one"
.LC6:
        .string "hides"
.LC7:
        .string "five"
.LC8:
        .string "amazing"
.LC9:
        .string "secrets"
MY_LIST:
        .quad   .LC0
        .quad   .LC1
        .quad   .LC2
        .quad   .LC3
        .quad   .LC4
        .quad   .LC5
        .quad   .LC6
        .quad   .LC7
        .quad   .LC8
        .quad   .LC9
someAlgebra:
        push    rbp                     ;save caller frame pointer
        mov     rbp, rsp                ;set frame pointer for this procedure
        mov     DWORD PTR [rbp-20], edi ;store param #1 (3)
        mov     DWORD PTR [rbp-24], esi ;store param #2 (5)
        mov     DWORD PTR [rbp-4], 4    ;store int a (local var)
        mov     DWORD PTR [rbp-8], 3    ;store int b (local var)
        mov     eax, DWORD PTR [rbp-20] ;Math in function body
        lea     ecx, [rax+rax]          ;Math in function body
        mov     edx, DWORD PTR [rbp-24] ;Math in function body
        mov     eax, edx                ;Math in function body
        add     eax, eax                ;Math in function body
        add     eax, edx                ;Math in function body
        lea     edx, [rcx+rax]          ;Math in function body
        mov     eax, DWORD PTR [rbp-4]  ;Math in function body
        add     eax, edx                ;Math in function body
        sub     eax, DWORD PTR [rbp-8]  ;Math in function body
        pop     rbp                     ;restore caller frame pointer
        ret                             ;pop return address into the PC
printAll:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        mov     QWORD PTR [rbp-24], rdi
        mov     DWORD PTR [rbp-28], esi
        mov     DWORD PTR [rbp-4], 0
        jmp     .L4
.L5:
        mov     eax, DWORD PTR [rbp-4]
        lea     rdx, [0+rax*8]
        mov     rax, QWORD PTR [rbp-24]
        add     rax, rdx
        mov     rax, QWORD PTR [rax]
        mov     rdi, rax
        call    puts
        add     DWORD PTR [rbp-4], 1
.L4:
        mov     eax, DWORD PTR [rbp-4]
        cmp     eax, DWORD PTR [rbp-28]
        jb      .L5
        nop
        nop
        leave
        ret
main:
        push    rbp                     ;save contents of rbp to stack
        mov     rbp, rsp                ;set frame pointer
        sub     rsp, 32                 ;reserve 32 bytes for local vars ??
        mov     DWORD PTR [rbp-20], edi ;??
        mov     QWORD PTR [rbp-32], rsi ;??
        mov     esi, 5                  ;param #2 for someAlgebra()
        mov     edi, 3                  ;param #1 for someAlgebra()
        call    someAlgebra             ;push return address to stack
        mov     DWORD PTR [rbp-4], eax  ;get return value from someAlgebra()
        mov     eax, 0
        leave
        ret
1 Answers

Regarding your ??s, when optimizations are off, gcc ensures that every local variable lives in memory, which includes function parameters. So the parameters argc, argv, despite the fact that they are passed to main in the registers edi, rsi, need to be stored in memory at an appropriate location on the stack.

Of course this is completely useless for the execution of the code, since those values are never loaded back, nor indeed are those parameters used at all. So the compiler could remove that code - but guess what, that'd be an optimization, and you told the compiler not to do any of those.

Although you might not think it, in most cases, reading optimized code is more educational, and less confusing, than unoptimized.

Related