Assembler output listing

My comments are tagged with the C comment characters.

.file	"fCall.c"    // the original source file
.def	___main;	.scl	2;	.type	32;	.endef
.text              // this goes into the text segment
LC0:                 // a gnerated label to store the string value
.ascii "hello\0"   // note that the string goes into TEXT segment!
.align 2           // tells linker to align this section on a two byte border
.globl _main         // puts our main in the .global section
.def	_main;	.scl	2;	.type	32;	.endef
_main:               // this is where our main really starts
pushl	%ebp           // save frame (base) pointer on stack
movl	%esp, %ebp     // store stackpointer in framepointer
subl	$24, %esp      // decrement stack pointer to make room 
                     // for main's local variables and future call arguments
andl	$-16, %esp   
movl	$0, %eax       // put 0 into eax register
movl	%eax, -16(%ebp) // move content of eax to where framepointer points 
                      // but with offset -16 
movl	-16(%ebp), %eax // get framepointer offset -16 into eax ???
call	__alloca       // call a c-runtime function to allocate memory
call	___main        // call a c-runtime function __main
                      
movl	$LC0, -4(%ebp) // get the address of LC0 (our string) and put it to 
                     // framepointer -4 on the stack. This is not surprisingly
                     // where our first local variable "string" lives.
movl	$0, -8(%ebp)   // put a 8 at framepointer -8 where our second var lives 
                     // (result)
movl	$1, -12(%ebp)  // put 1 at framepointer -12 where our third var (arg1)lives
movl	-12(%ebp), %eax// move arg1 from stack into register eax
movl	%eax, (%esp)   // put eax content on stack. Note, this is the leftmost 
                     // argument for function call!!!
movl	-4(%ebp), %eax // put the string address from stack into eax
movl	%eax, 4(%esp)  // and put it from there onto the stack
                     // now we have set up the stack with two arguments and can 
                     // call our function. 
                     // You will need to look at _myFunc to see how the arguments
                     // are processed by our function.
call	_myFunc        // tell CPU to push the current instruction address on the 
                     // stack (saving it for return) and move the address where  
                     // _myFunc lives into the instruction register
//----------------------------------------------------
// after we come back from the call to _myFunc:
movl	%eax, -8(%ebp) // in eax is the return value from our function call
                     // with a debugger you would find 44 here
movl	$0, %eax       // generate main's return value (0 for everything OK)
leave                // restore framepointer and stackpointer to how they
                     // where BEFORE main function was running
ret                  // tell CPU to get return address (the address from where 
                     // our main was called) and jump to it, effectively continuing 
                     // callers processing right after the function call to main.
                     // in this case this would mean jumping back into the
                     // C-runtime code which started our program.
//-----------------------------------------------------
.align 2
.globl _myFunc
.def	_myFunc;	.scl	2;	.type	32;	.endef
myFunc:
pushl	%ebp           //save framepointer from caller (prolog)
movl	%esp, %ebp     // put stackpointer into framepointer which
                     // is now our vehicle to access OUR (myFunc's) local
                     // variables and arguments
subl	$8, %esp       // make room on stack for 8 bytes
movl	8(%ebp), %eax  // move 4 bytes from framepointer offset 8 into eax register
movl	%eax, -4(%ebp) // move those bytes now into local variable at offset -4 
                     // what does: int localVar = intPar;    
movl	12(%ebp), %eax // again move 4 bytes from offset 12 into eax 
movl	%eax, -8(%ebp) // and store them at offset -8 which makes:
                    //     char* localString = stringPar;
movl	$44, %eax     // put decimal 44 into register eax which
                    // creates our RETURN value (must be in eax as we 
                    // will see when we look at how the caller receives this
                    // value: return 44;
leave               // clean up the local calling frame (restore framepointer and
                    // stack pointer to HOW THE CALLER LEFT THEM. Any surprise here 
                    // is not really funny.
ret                 // tells the cpu to take the callers return address from stack
                    // into the instruction pointer register and continue executing