### Annotated assembly code for factorial_test.c . ### This assembly code uses the GNU assembler (gas) syntax; ### which is what you learned in class, except that comments ### start with # rather than ; . .file "factorial_test.c" .text .globl factorial .type factorial, @function ### int factorial (int n); ### n ==> 8(%ebp) - (%ebp) is old %ebp, 4(%ebp) is return address, so ### 8(%ebp) is first and only argument ### Return value ==> %eax (the register) ### Temp. value t1 ==> %eax ### Temp. value t2 ==> -12(%ebp) (location on stack) ### N.B. %eax is overloaded as both return value and temp. value factorial: ## [prologue] pushl %ebp # Push old frame pointer %ebp on stack movl %esp, %ebp # %ebp := %esp (currently pointing to old %ebp) subl $40, %esp # Allocate 40-byte stack frame (no push/pop for us) ## if (n <= 0) { ## return (1); ## } cmpl $0, 8(%ebp) # Compute n-0 (== n) - don't store result, # but set condition codes jg fact_positive # if (n > 0) goto fact_positive movl $1, %eax # result := 1 jmp fact_end # goto fact_end fact_positive: ## else { ## int recursive_result = factorial(n-1); ## return (n * recursive_result); ## } movl 8(%ebp), %eax # t1 (%eax) := n subl $1, %eax # t1 -= 1 movl %eax, (%esp) # copy t1 to last word in our stack frame call factorial # push return addr on stack, goto recursive call movl %eax, -12(%ebp) # t2 (-12(%ebp)) := recursive call's result movl 8(%ebp), %eax # result := n imull -12(%ebp), %eax # result *= t2 (truncate upper word of product) fact_end: ## [epilogue] leave # pop stack frame (%esp := %ebp), pop and restore old %ebp ret # pop return address, return there (to caller) .size factorial, .-factorial .section .rodata format: .string "%d\n" .text .globl main .type main, @function ### int main (void); ### result ==> 28(%esp) ### temp value t1 ==> %eax ### temp value t2 ==> %edx main: ## [prologue] pushl %ebp # save old %ebp movl %esp, %ebp # set up new %ebp andl $-16, %esp # decrease %esp enough to clear bottom 4 bits # (to align the stack frame) subl $32, %esp # 32-byte stack frame ## int result = factorial(10); movl $10, (%esp) # store 10 in last word of stack frame # (first arg to factorial) call factorial # call factorial(10) movl %eax, 28(%esp) # result := factorial result ## printf ("%d\n", result); movl $format, %eax # t1 (%eax) := address of "%d\n" movl 28(%esp), %edx # t2 (%edx) := result movl %edx, 4(%esp) # store factorial result to 2nd to last word # (second arg of printf()) movl %eax, (%esp) # store "%d\n" address to last word (1st arg) call printf # call printf ("%d\n", result) ## return (0); movl $0, %eax # main's result := 0 ## [epilogue] leave # pop stack frame, restore old %ebp ret # return to caller (OS) .size main, .-main .ident "GCC: (GNU) 4.4.5 20101112 (Red Hat 4.4.5-2)" .section .note.GNU-stack,"",@progbits