Nonrecursive Factorial & Factorial Comparison

VSBrown 0 Tallied Votes 593 Views Share

A program that will test the Nonrecursive Factorial procedure using a value passed in by the program user and will also do a time comparision of the Nonrecursive and Recursive Factorial functions.

TITLE: NonrecursiveFactorial&FactorialComparison (Factorials.asm)

;------------------------------------------------------------
; Name: 
;
; Filename: Factorials.asm
;
; Project #: 6
;
; Completed: March 15, 2003
;
; Description: My sixth assembly program. A program that will
;              test the Nonrecursive Factorial procedure using
;              a value passed in by the program user and will
;              also do a time comparision of the Nonrecursive
;              and Recursive Factorial functions.
;              From Assembly Language For Intel-Based Computers,
;              4th Ed. by Kip R. Irvine. 
;              (Problem #3 and #4 on pg. 298)
;
; Reference:   Assembly Language For Intel-Based Computers,
;              4th Ed. by Kip R. Irvine
;              (Section 8.5.2 Calculating a Factorial)
;              (Fact.asm)
;------------------------------------------------------------
INCLUDE Irvine32.inc

.data
startTime dword 0
savedNum  sdword ?
numOfTimes = 00000FFFh;(squared) to calculate the factorial
caseTable byte '1'                ;lookup value
          dword enterInt          ;address of lookup value
entrySize = ($ - caseTable )
          byte '2'
          dword factCompare
          byte '3'
          dword endTest
          numberOfEntries = 3
msgIntro  byte "This is Your Name's sixth assembly program. A program that will",0dh,0ah
          byte "test the Nonrecursive Factorial procedure using a value passed in",0dh,0ah
          byte "by the program user and will also do a time comparision of the ",0dh,0ah
          byte "Nonrecursive and Recursive Factorial functions.",0dh,0ah,0
msgSelMn  byte " -----------------------------------------",0dh,0ah
          byte "|                 MENU:                   |",0dh,0ah
          byte "| 1. NonRecursive Factorial (Exercise #3) |",0dh,0ah
          byte "| 2. Factorial Comparison   (Exercise #4) |",0dh,0ah
          byte "| 3. Exit Program                         |",0dh,0ah
          byte " -----------------------------------------",0dh,0ah
          byte "Enter Selection: ",0
msgInputN byte "Enter the value of n to calculate. "
	  byte "( n must be <= 12 ) : ",0
msgFact   byte "Factorial =  ",0
msgError  byte "Sorry cannot calculate the following factorial because "
          byte "it is greater than 12! ",0dh,0ah
          byte "                                12 < ",0
msgNonRec byte "The time to do the Nonrecursive factorial = ",0
msgRec    byte "The time to do the Recursive factorial = ",0
msgEnd    byte "End Program",0dh,0ah,0

.code
main PROC
;///////Intro Message/////////////////////////////////
	mov edx,OFFSET msgIntro  ;intro message into edx
        call WriteString         ;display msgIntro
        call Crlf                ;endl
        call WaitMsg             ;pause message
        call Clrscr              ;clear screen
        call Menu                ;menu procedure

ExitProg::exit                   ;global label to exit
main ENDP

;------------------------------------------------
Menu PROC
;
; Receives: Nothing
; Returns: Nothing
;------------------------------------------------
	mov  edx,OFFSET msgSelMn ;ask user for input
	call WriteString         ;display msgSelMn
	call ReadChar		 ;read one character
	call Clrscr
        mov  ebx,OFFSET caseTable;point EBX to the table
	mov  ecx,numberOfEntries ;loop counter

        L1:
	cmp  al,[ebx]		 ;match found?
	jne  L2		         ;no: continue
	call NEAR PTR [ebx + 1]	 ;yes: call the procedure
	call WriteString	 ;display message
	call Crlf                ;endl
	call Clrscr              ;clear screen
	jmp  L3		         ;exit the search

        L2:
	add  ebx,5		 ;point to the next entry
	loop L1		         ;repeat until ECX = 0

        L3:
	jmp Menu	         ;run Menu again

Menu ENDP

;------------------------------------------------
enterInt PROC
;
; User input of n
; Receives: EAX = n
; Returns: EAX = n
;------------------------------------------------
    	mov edx, OFFSET msgInputN ;ask user to input n
    	call WriteString
    	call ReadInt	          ;int input by user
    	mov savedNum,eax
    	call Crlf
    	cmp eax, 0	          ;is n less than 0
    	jl endTest

    	mov edx, OFFSET msgFact
    	call WriteString
    	call nonRecurFact	  ;EAX = factorial(n)
    	call WriteDec	          ;display factorial
    	call Crlf
    	call Crlf
    	call WaitMsg
    	ret

enterInt ENDP

;-------------------------------------------------------
Factorial PROC
;
; Calculates a factorial
; Receives: [ebp+8] = n, the number to calculate
; Returns: EAX = factorial of n
;--------------------------------------------------------
;(Fact.asm)
	push ebp	         ;save stack base pointer
	mov  ebp, esp
	mov  eax, [ebp+8]	 ;get n
	cmp  eax, 0	         ;is n < 0?
	ja   L1	                 ;yes: continue
	mov  eax, 1	         ;no: return 1
	jmp  L2

        L1:
        dec  eax
	push eax	         ;Factorial(n-1)
	call Factorial

;Instructions from this point on execute when each
;recursive call returns.

        ReturnFact:
	mov  ebx, [ebp+8]	 ;get n
	mul  ebx	         ;edx:eax = eax * ebx

        L2:
        pop  ebp	         ;return EAX
	ret  4	                 ;clean up stack

Factorial ENDP

;------------------------------------------------
nonRecurFact PROC USES ECX EDX
;
; Calculates Nonrecursive Factorial
; Receives: EAX = n (as input by user)
; Returns: EAX = nonrecursive factorial
;------------------------------------------------
	.IF eax == 0 || eax == 1  ;special cases
	  mov eax, 1	          ;factorial == 1
	  jmp L2         	  ;quit procedure
	.ELSEIF eax > 12	  ;n is too large
	  mov edx, OFFSET msgError
	  call Crlf
	  call WriteString
	  jmp L2	          ;quit procedure
	.ENDIF

	mov ecx, eax	          ;ecx = counter

        L1:
	dec ecx	                  ;ecx = n - 1
	mul ecx	                  ;eax = n * (n - 1)

	cmp ecx, 1	          ;is counter > 1?
	ja L1	                  ;true? then continue

	L2:
	ret

nonRecurFact ENDP

;------------------------------------------------
factCompare PROC
;
; Receives: Nothing
; Returns: Nothing
;------------------------------------------------
        call enterInt
        mov ecx, numOfTimes	 ;counter
	call GetMseconds	 ;get miliseconds since midnight
	mov startTime, eax	 ;save start time

        L1:
	push ecx	         ;save outer loop counter
	mov ecx, numOfTimes	 ;counter inner loop

	L2:
	mov eax, savedNum
	call nonRecurFact        ;nonRecursive factorial
	loop L2	                 ;next inner loop iteration

	pop ecx	                 ;restore outer loop
	loop L1	                 ;inner loop

	call GetMseconds	 ;get miliseconds since midnight
	sub eax, startTime	 ;get running time
	mov edx, OFFSET msgNonRec
	call WriteString
	call WriteDec	         ;display time
	call Crlf

	mov ecx, numOfTimes	 ;counter
	call GetMseconds	 ;get miliseconds since midnight
	mov startTime, eax	 ;save starting time
        L3:
	push ecx	         ;save outer loop counter
	mov ecx, numOfTimes	 ;counter inner loop

	L4:
	push savedNum
	call Factorial	         ;recursive factorial
	loop L4	                 ;inner loop

	pop ecx	                 ;restore outer loop counter
	loop L3

	call GetMseconds	 ;get miliseconds since midnight
	sub eax, startTime	 ;get running time
	mov edx, OFFSET msgRec
	call WriteString
	call WriteDec	         ;display time
	call Crlf
	call Crlf
	call WaitMsg
	ret

factCompare ENDP

;------------------------------------------------
endTest PROC
;
; Receives: Nothing
; Returns: EDX = offset of message
;          Sets CF = 1 to signal end of program
;------------------------------------------------
        mov  edx,OFFSET msgEnd   ;msgEnd into edx
	call WriteString	 ;display message
	call Crlf                ;endl
	stc	                 ;CF = 1
	jc ExitProg    	         ;if CF=1 then jump to Global ExitProg

endTest ENDP

END main