I tested this C code on Compiler Explorer:
#include <stdio.h>
int main(void)
{
printf("Hello world!\n");
}
I selected the compiler x86-64 gcc 12.2
with the parameters -std=c17 -O3 -m32
.
In 64-bit mode (no -m32
option) the output looks OK and optimized (online example):
.LC0:
.string "Hello world!"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0
call puts
xor eax, eax
add rsp, 8
ret
In 32-bit mode, the output is bloated by a lot of non-sense (online example):
.LC0:
.string "Hello world!"
main:
lea ecx, [esp+4] # OK, so ecx = esp + 4, but main has no parameters...why?
and esp, -16
push DWORD PTR [ecx-4] # push [ecx - 4], which is the return address...why?
push ebp
mov ebp, esp
push ecx # saves the stack address above the return address...what is going on?
sub esp, 16 # what is this for?
push OFFSET FLAT:.LC0
call puts
mov ecx, DWORD PTR [ebp-4] # restores that address
add esp, 16 # cleans that add esp, 16??
xor eax, eax
leave
lea esp, [ecx-4] # restores stack as it was on function entry
ret
I expected something along the lines of:
.LC0:
.string "Hello world!"
main:
sub esp, 12 # GCC wants 16-byte aligned stack
push OFFSET FLAT:.LC0
call puts
xor eax, eax
add esp, 12
ret
Considering I used the -O3
option, why does the output look like that?