;;; Auteur: Younes EL Amrani ;;; PREMIERE Modification: March 26, 2007 ;;; Révision 1: dimanche 25 avril 2009 ;;; Révision 2: samedi 01 mai 2010 ;;; Fichier: factoriel.asm : version recursive ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Use libc input/output functions printf and scanf ;;; Avec windows/mingw, on doit prefixer les globales avec _ (underscore) ;;; when you want to call the asm factorial from C use the following: ;;; global _fact; used when main defined in callerfactoriel.c extern _printf, _scanf global _main, _fact ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; macro print : affichage avec appel a _printf de libgcc %macro print 2 push %2 push %1 call _printf add esp, 8 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; macro scan : lecture avec appel a _scanf de libgcc %macro scan 2 push %2 push %1 call _scanf add esp, 8 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; SEGMENT des Donnees initialisees: SEGMENT .data invite: db "Entrer un entier pour en calculer le factoriel" , 0 integerFormat: db "%d" , 0 textFormat: db "%s" , 0 newline: db 13, 10, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; SEGMENT des donnees non initialisees: ;;; dans Nfact nous allons mettre le resultat de factoriel SEGMENT .bss N: resd 1 Nfact: resd 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Segment des instructions executables SEGMENT .text _fact: .f1: push ebp .f2: mov ebp, esp .f3: mov eax, dword [ebp+8] .f4: cmp eax, 1 ; comparer N et 1 .f5: jle .FIN_APPEL ; si (N <= 1) On termine avec EAX = 1 .f6: dec eax ; Sinon, on fait un appel récursif _fact(N-1) .f7: push eax ; empiler N-1 .f8: call _fact ; appeler _fact(N-1) .f9: add esp, 4 ; depiler N-1 .f11: imul dword [ebp+8] ; EAX = fact(N-1) et EAX' = N*fact(N-1) .FIN_APPEL: .f12: mov esp, ebp .f13: pop ebp .f14: ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _main: .m1: enter 0, 0 ;;; print textFormat, invite .m2: scan integerFormat, N ; Lire la valeur de N .m3: push dword [ N ] ; Empiler le parametre N .m4: call _fact ; appeler _fact(N) .m5: add ESP , 4 ; depiler le parametre N .m6: mov DWORD [Nfact] , EAX ; affecter [Nfact] = _fact(N) = N! ;.m7: print integerFormat , EAX ; afficher EAX = _fact(N) .m8: print textFormat, newline ; afficher une nouvelle ligne print integerFormat, DWORD [ Nfact ]; re-afficher [Nfact] = N! .m9: mov EAX, 0 .m10: leave .m11: ret