Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Factorial calculation

Started by skinnyg, May 15, 2013, 10:17:20 AM

Previous topic - Next topic


Ok writing a prog to check factorial then display message if does not fit in 32bit space.. cant fig that part out.. i know i gotta check for over flow then display when it cant fit in 32bit..any assistance would be is the code.. i def will continue to try..(head is pounding..  :redface:  )



factormsg BYTE "Enter the value of n to calculate the factorial (-1 to quit): ",0
factordisplay BYTE "The factorial is: ",0
factorError BYTE "Error: Result does not fit in 32 bits.",0


main PROC
   mov edx, OffSet factormsg
   Call WriteString
   Call Readint
   mov edx, Offset factordisplay
   Call WriteString

   .if eax== -1
   ;Call Crlf

   push eax ; push user entered interger on stack

call Factorial ; calculate factorial (EAX)
call WriteDec ; display it
call Crlf

loop L1

main ENDP
Factorial PROC
; Calculates a factorial.
; Receives: [ebp+8] = n, the number to calculate
; Returns: eax = the factorial of n
push ebp
mov ebp,esp
mov eax,[ebp+8] ; get n

cmp eax,0 ; n  0?
   ja L1 ; yes: continue
mov eax,1 ; no: return 1 as the value of 0!

   jmp L2 ; and return to the caller

L1: dec eax

push eax ; Factorial(n1)

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


mov ebx,[ebp+8] ; get n
   mul ebx ; EDX:EAX = EAX * EBX
   L2: pop ebp ; return EAX
   ret 4 ; clean up stack
Factorial ENDP
END main


there are some sieve type algorithms for this
probably one of the simplest is the sieve of Eratosthenes

you could create a 512 Mb file, with 1 bit for each value from 0 to 4294967295
one little program to create the file
and another program to open and read the file, and test values


the overflow can be detected by testing EDX after the multiplications:
mul ebx
test edx,edx
jnz @largerThan32Bit

Because you are using a recursive algorithm, you must find a way to notify the "upper level" that an overflow occurs. This could be done by using a register (e.g. ECX) or adding a second parameter to the function, which is a pointer to a Boolean variable (e.g. Factorial  proto n:DWORD,pOverflow: ptr BOOL). An other solution is to use the carry flag (instructions: set/clear carry: stc/clc).
MREAL macros - when you need floating point arithmetic while assembling!


.model flat, stdcall
option casemap:none
include \masm32\include\
includelib \masm32\lib\user32.lib
extrn _imp__MessageBoxA@16:dword
n equ 73
start:  mov edi,offset result+len;edi - pointer to the last byte of the result
    mov esi,n
    mov dword ptr [edi-4],esi
    sub edi,8
    mov ebp,1
    dec esi
@1: mov ecx,ebp
    xor ebx,ebx
@@: mov eax,dword ptr [edi+4*ecx]
    mul esi
    add eax,ebx
    adc edx,0
    mov ebx,edx
    mov dword ptr [edi+4*ecx],eax
    loop @b;.untilcxz
    je @2;  .if !ZERO?
    mov dword ptr [edi],edx
    cmp dword ptr [edi+4*ebp],0
    je @f
    inc ebp
@@: sub edi,4
@2: dec esi
    jne @1;.until ZERO?
; big-endian --> litle-endian
    mov edi,offset result
    mov cl,len/4;length of the result in the DWORD
@@: mov eax,[edi]
    bswap eax
    loop @b
; translate hex->dec
    mov esi,offset terminator-1;
@3: mov cl,len;length in bytes of the value of the dividend
    mov edi,offset result
    xor eax,eax
@@: mov al,[edi];dividend
    div ten
    loop @b
    or [esi],ah;remain
    dec esi
    cmp dword ptr [edi-4],0;cmp result+36,0
    jne @3
    cmp dword ptr [edi-8],0;cmp result+32,0
    jne @3
    cmp dword ptr [edi-12],0;cmp result+32,0
    jne @3
;screen output
    inc esi
    push offset mesbox_title   
    push esi;offset mesbox_text adjusted for leading zeros
    push 0
    call _imp__MessageBoxA@16
result  db 44 dup (0)
len = $-result
ten db 10
mesbox_text db 112 dup ('0')
terminator db 0
mesbox_title db 'Factorial calculation',0
end start


i was thinking primes
DOH !   :redface:


push N ;compute N factorial
call fact ;call procedure
push edi ;edi=N! the result is here
push offset format
push offset buffer
call _imp__wsprintfA
add esp,12 ;align the stack after wsprintfA
push 0
push offset caption
push offset buffer
push 0
call _imp__MessageBoxA@16 ;output the result on the screen
ret;exit the program
;structure of the stack frame
;[esp] saved return address of the procedure
;[esp+4] place for N
fact proc
mov ecx,[esp+4];ecx=N
jecxz done ;N equal 0?
dec ecx ;for the next call
push ecx ;included in the stack ecx=N-1
call fact
mov eax,edi ;in edi the value of the previous result
mul dword ptr [esp+4] ;eax=N*edi
jmp short rtrn
done: mov eax,1 ;eax=1
rtrn: mov edi,eax;return the new value of the result in edi
retn 4 ;remove unnecessary local variables
fact endp
format db 'factorial=%lu',0
buffer db 50 dup (0)
caption db ' factorial',0


1700! =  2.99835320555842E+4755


Thanks everyone... it was a great help.. :t