C program:
#include <stdio.h>
int main(void) {
puts("Hello World!\n");
return 0;
}
Compile without assembling - the preferred stack boundary is set to a single word (22 bytes) to avoid confusing boilerplate stack alignment code:
gcc -S -mpreferred-stack-boundary=2 hello.c
Result:
.file "hello.c"
.section .rodata # constant data section (read-only data)
.LC0: # constant string declaration
.string "Hello World!\n"
.text # instruction section
.globl main # keep 'main' symbol for linking
.type main, @function # 'main' symbol is a function
main: # the next instruction is the start of
# 'main'
pushl %ebp # save caller base pointer
movl %esp, %ebp # callee base pointer = current stack pointer
subl $4, %esp # allocate a single word for string address
movl $.LC0, (%esp) # copy string address to top of stack
# (first and only parameter to puts)
call puts # set return address and jump to puts code
# (which is linked in)
movl $0, %eax # return 0
leave
ret # return to caller(_start in the C library)
.size main, .-main # sizeof(main) is from 'main' to here
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.10)"