Why is this stack variable in C not in a register?

100 views Asked by At

I have a reasonable understanding of how to execute buffer overflow attacks and how register allocation works in compilers.

What confuses me is why so many things are on the stack in C programs. Consider this vulnerable program:

#include <stdio.h>

int main() {
    int a = 0;
    char str[] = "ABC";
    gets(str);
    printf("int: %d, str: %s\n", a, str);
    return a;
}

Let's run it

> gcc run.c
> ./a.out asdfasdf
int: 1717859169, str: asdfasdf

Okay so str is overwritten as is int a. But why is int a even on the stack? Wouldn't it be easiest to just do something like (x86 asm)

.global _main
.text
_main:
        // omitting the gets() stuff
        movq $0, %rax
        retq

Now we have less memory traffic since nothing is on the stack and much less code.

tl;dr why is int a on the stack at all?

1

There are 1 answers

0
nlta On

Per the comments on my post. It happens because I am compiling without optimization and when I compile with optimizations gcc -O3 run.c I won't see the same behavior.

Here's some of the optimized assembly

> gcc -o run -O3 run.c
> objdump -d run

...
// Set eax = 0
100003f5c: 31 c0                        xorl    %eax, %eax  
100003f5e: 48 83 c4 08                  addq    $8, %rsp
100003f62: 5b                           popq    %rbx
100003f63: 5d                           popq    %rbp
// Return 0
100003f64: c3                           retq                

And the more complicated unoptimized:

...
// put 0 on the stack
100003f33: c7 45 f8 00 00 00 00         movl    $0, -8(%rbp) the stack
...
// take it off the stack and into ecx
100003f61: 8b 4d f8                     movl    -8(%rbp), %ecx 
100003f64: 89 45 e4                     movl    %eax, -28(%rbp)
100003f67: 89 c8                        movl    %ecx, %eax
100003f69: 48 83 c4 20                  addq    $32, %rsp
100003f6d: 5d                           popq    %rbp
// return 0
100003f6e: c3                           retq