; test_factorial.asm based on test_factorial.c ; /* test_factorial.c the simplest example of a recursive function */ ; /* a recursive function is a function that calls itself */ ; static int factorial(int n) /* n! is n factorial = 1*2*3*...*(n-1)*n */ ; { ; if( n <= 1 ) return 1; /* must have a way to stop recursion */ ; return n * factorial(n-1); /* factorial calls factorial with n-1 */ ; } /* n * (n-1) * (n-2) * ... * (1) */ ; #include ; int main() ; { ; printf(" 0!=%d \n", factorial(0)); /* Yes, 0! is one */ ; printf(" 1!=%d \n", factorial(1)); ; ... ; printf("18!=%d \n", factorial(18)); /* wrong, uncaught in C */ ; return 0; ; } ; /* output of execution is: ; 0!=1 ; 1!=1 ; ... ; 12!=479001600 ; 13!=1932053504 wrong! 13! = 12! * 13, must end in two zeros ; 14!=1278945280 wrong! and no indication! ; 15!=2004310016 wrong! ; 16!=2004189184 wrong! ; 17!=-288522240 wrong and obvious if you check your results ; 18!=-898433024 Only sometimes does integer overflow go negative ; */ ; ; compile: nasm -f elf test_factorial.asm ; link: gcc -o test_factorial.o ; run: test_factorial section .bss tmp: resd 1 ; over written each call section .text factorial: push ebp ; function int factorial(int n) mov ebp,esp push ebx mov eax,[ebp+8] ; get argument n cmp eax,1 ; compare for exit jle exitf ; go return a 1 sub eax,1 ; n-1 push dword eax ; compute factorial(n-1) call factorial pop edx ; get back our "n-1" add edx,1 ; have our "n" mov [tmp],edx imul eax,[tmp] ; n * factorial(n-1) in eax jmp returnf exitf: mov eax,1 returnf: pop ebx mov esp,ebp pop ebp ret ; return value in eax ; end of function static int factorial(int n) extern printf section .data n: dd 0 ; initial, will count to 18 fmt: db "%d! = %d",10,0 ; simple format section .bss nfact: resd 1 ; just a place to hold result section .text global main main: push ebp mov ebp,esp push ebx loop1: push dword [n] ; push arguments for factorial call factorial ; coded above add esp,4 mov [nfact],eax ; save result from factorial push dword [nfact] ; print push dword [n] push dword fmt call printf add esp,12 mov eax,[n] inc eax mov [n],eax cmp eax,18 jle loop1 ; print factorial 0..18 pop ebx mov esp,ebp pop ebp mov eax,0 ret ; end main