I write empty programs to annoy the hell out of stackoverflow coders, NOT. I am just exploring the gnu toolchain.
Now the following might be too deep for me, but to cont
There's a very similar exercise outlined here: http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax
You've figured out most of it -- I'll just make additional notes for emphasis and additions.
__main
is a subroutine in the GNU standard library that takes care of various start-up initialization. It is not strictly necessary for C programs but is required just in case the C code is linking with C++.
_main
is your main subroutine. As both _main
and __main
are code locations they have the same storage class and type. I've not yet dug up the definitions for .scl
and .type
yet. You may get some illumination by defining a few global variables.
The first three instructions are setting up a stack frame which is a technical term for the working storage of a subroutine -- local and temporary variables for the most part. Pushing ebp
saves the base of the caller's stack frame. Putting esp
into ebp
sets the base of our stack frame. The andl
aligns the stack frame to a 16 byte boundary just in case any local variables on the stack require 16 byte alignment (for the x86 SIMD instructions require that alignment, but alignment does speed up ordinary types such as int
s and float
s.
At this point you'd normally expect esp
to get moved down in memory to allocate stack space for local variables. Your main
has none so gcc doesn't bother.
The call to __main
is special to the main entry point and won't typically appear in subroutines.
The rest goes as you surmised. Register eax
is the place to put integer return codes in the binary spec. leave
undoes the stack frame and ret
goes back to the caller. In this case, the caller is the low-level C runtime which will do additional magic (like calling atexit()
functions, set the exit code for the process and ask the operating system to terminate the process.