Different ways how gcc allocate memory for stack

338 views Asked by At

How does gcc decides how much memory allocate for stack and why does it not decrement %rsp anymore when I remove printf() (or any function call) from my main?

1. I noticed when I played around with a code sample: https://godbolt.org/z/fQqkNE that the 6th line in gcc assembly viewer subq $48, %rsp gets removed if I remove printf() from my C code on line 22. It looks like when I don’t make any function calls from within my main, then the %rsp does not get decremented, but data still gets allocated based on %rbp and offsets. I thought %rsp changes only when stack grows. My theory is that since it won’t make any other function calls, it knows that it won’t need to keep stack for other nonexistent functions. But shouldn’t %rsp still grow as data is getting saved?

2. When adding variables to my rect struct, I also noticed that it sometimes allocates memory in steps greater than what the added data type size was. What is the convention it follows when deciding how much memory to allocate to stack?

3. Is there an online tool that would take assembly code as input, and then draw an image of stack and tell me state of every register at any point of execution? Godbolt.org is a very good tool, I just wish it had these 2 extra features.

I'll paste the code below in case the link to godbolt stops working in the future:

#include <stdio.h>
#include <stdint.h>
struct rect {
    int a;
    int b;
    int* c;
    int d[2];
    uint8_t f;
};

int main() {
    int arr[2] = {2, 3};
    struct rect Rect;
    Rect.a = 10;
    Rect.b = 20;
    Rect.c = arr;

    Rect.d[0] = Rect.a;
    Rect.d[1] = Rect.b;

    Rect.f =255;
    printf("%d and %d", Rect.a, Rect.b);

    return 0;
}
.LC0:
        .string "%d and %d"
main:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $48, %rsp
        movl    $2, -8(%rbp)
        movl    $3, -4(%rbp)
        movl    $10, -48(%rbp)
        movl    $20, -44(%rbp)
        leaq    -8(%rbp), %rax
        movq    %rax, -40(%rbp)
        movl    -48(%rbp), %eax
        movl    %eax, -32(%rbp)
        movl    -44(%rbp), %eax
        movl    %eax, -28(%rbp)
        movb    $-1, -24(%rbp)
        movl    -44(%rbp), %edx
        movl    -48(%rbp), %eax
        movl    %eax, %esi
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        leave
        ret

P.S.: The book I follow uses AT&T syntax for teaching x86. Which is weird because it makes finding online tutorials much harder.

0

There are 0 answers