Hi All;
Here is a Factorial Program.
It only works to 12!
Also needs a 64 bit to Ascii routine to
convert DX:AX to String.
; FACT.ASM Sunday, October 05, 2008 4:24 PM
include \masm32\include\masm32rt.inc
.data
public crlf
crlf db 13,10,0
.code
Start:
call main
inkey
exit
ret
main proc
LOCAL N:DWORD
LOCAL A:DWORD
LOCAL buffer[20]:byte
LOCAL buf:DWORD
mov N, sval(input(" Factorial of " ))
print chr$(32)
mov eax, N
mov A, eax
mov ebx, eax
and eax, eax
jz loopErr
js loopNeg
mov buf, ptr$(buffer)
invoke crt__ultoa, N, buf, 10
print buf, 32
begin:
print chr$('*')
mov ebx, N
cmp ebx, 1
jz loopExit
mov eax, N
dec ebx
mov N, ebx
mov buf, ptr$(buffer)
invoke crt__ultoa, N, buf, 10
print buf, 32
mov edx, 0
mov eax, A
mul ebx
jc overflow
mov A, eax
cmp ebx, 1
jz loopExit
mov buf, ptr$(buffer)
invoke crt__ultoa, A, buf, 10
print chr$('=')
print buf, 32
cmp ebx, 2
jz loopExit
jmp begin
loopNeg:
print "Negative", 13 , 10, 7
jmp X
loopErr:
print "Zero is Invalid", 13, 10, 7
jmp X
overflow:
print " Overflow has occured", 13, 10
loopExit:
X:
mov eax, A
and eax, eax
jz @F
cmp eax,3
jnc @F
mov buf, ptr$(buffer)
invoke crt__ultoa, A, buf, 10
print chr$('=')
print buf
@@:
print chr$(13, 10)
inkey
exit
main endp
end Start
Regards herge
QuoteAlso needs a 64 bit to Ascii routine to convert DX:AX to String.
I assume you mean EDX:EAX. You should be able to use
_i64toa (http://msdn.microsoft.com/en-us/library/yakksftt(VS.71).aspx) to do the conversion, but considering that you are displaying the string on the console, it would be easier to use
printf (http://msdn.microsoft.com/en-us/library/wc7014hz(VS.71).aspx) to do both.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
fact dq 0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
;-------------------------------------------------------------
; This proc uses the FPU to calculate the factorial, allowing
; it to handle 20! with a minimal number of instructions.
; Returns the factorial at the top of the FPU stack (in ST).
;-------------------------------------------------------------
factorial proc num:DWORD
fld1 ; ST = 1
mov eax, 1
.WHILE eax <= num
push eax ; Put EAX on the (program) stack
fild DWORD PTR [esp] ; Load the value just pushed into ST
; Running product now in ST(1)
pop eax ; Remove eax from the {program) stack
fmul ; ST = ST(1) * ST, ST(1)-ST(7) now empty
inc eax
.ENDW
ret
factorial endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
mov esi, 1
.WHILE esi <= 20
invoke factorial, esi
fistp fact ; Store the value in ST to fact as a 64-bit
; integer, all FPU registers now empty.
invoke crt_printf, chr$("%d",9,"%I64d%c"), esi, fact, 10
inc esi
.ENDW
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Hi MichaelW:
Your method is lot shorter than mine!
Yes i did mean EDX:EAX
Isn't redirection wonderful!
filename > temp.txt
Press any key to exit...
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
11 39916800
12 479001600
13 6227020800
14 87178291200
15 1307674368000
16 20922789888000
17 355687428096000
18 6402373705728000
19 121645100408832000
20 2432902008176640000
Regards herge
Hi MichaelW:
The sample c program is missing include string.h
Does strlen need it?
#include "stdafx.h"
#include "stdlib.h"
#include "string.h"
#include <conio.h>
int _tmain(int argc, _TCHAR* argv[])
{
char buffer[65];
int r;
for( r=10; r>=2; --r )
{
_itoa( -1, buffer, r );
printf( "base %d: %s (%d chars)\n", r, buffer, strlen(buffer) );
}
printf( "\n" );
for( r=10; r>=2; --r )
{
_i64toa( -1L, buffer, r );
printf( "base %d: %s (%d chars)\n", r, buffer, strlen(buffer) );
}
printf( "\n" );
for( r=10; r>=2; --r )
{
_ui64toa( 0xffffffffffffffffL, buffer, r );
printf( "base %d: %s (%d chars)\n", r, buffer, strlen(buffer) );
}
_getche( );
return 0;
}
Regards herge
I'm not sure what you are doing or how you are compiling, but I think the likely answer is that string.h is necessary. Why not just bypass the problem by converting the source over to a MASM32 project.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
i64 dq -1
u64 dq 0ffffffffffffffffh
buffer db 65 dup(0)
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
mov ebx, 10
.WHILE ebx > 1
invoke crt__itoa, -1, ADDR buffer, ebx
invoke crt_printf, chr$("base %d: %s (%d chars)%c"), ebx,
ADDR buffer, len(ADDR buffer), 10
dec ebx
.ENDW
print chr$(13,10)
mov ebx, 10
.WHILE ebx > 1
;--------------------------------------------------------------
; The _i64toa function expects the value to be a 64-bit signed
; integer passed on the stack. Since invoke knows how to pass
; 64-bit values on the stack, we can just pass the value in a
; QWORD variable.
;--------------------------------------------------------------
invoke crt__i64toa, i64, ADDR buffer, ebx
invoke crt_printf, chr$("base %d: %s (%d chars)%c"), ebx,
ADDR buffer, len(ADDR buffer), 10
dec ebx
.ENDW
print chr$(13,10)
mov ebx, 10
.WHILE ebx > 1
invoke crt__ui64toa, u64, ADDR buffer, ebx
invoke crt_printf, chr$("base %d: %s (%d chars)%c"), ebx,
ADDR buffer, len(ADDR buffer), 10
dec ebx
.ENDW
print chr$(13,10)
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
BTW, this is the code that invoke generated:
00401050 53 push ebx
00401051 6810304000 push 403010h
00401056 FF3504304000 push dword ptr [403004h]
0040105C FF3500304000 push dword ptr [403000h]
00401062 FF1518204000 call dword ptr [_i64toa]
00401068 83C410 add esp,10h
Hi MichaelW:
invoke crt_printf, chr$("%3d!= ","%I64d%c"), esi, fact, 10
Press any key to exit...
1!= 1
2!= 2
3!= 6
4!= 24
5!= 120
6!= 720
7!= 5040
8!= 40320
9!= 362880
10!= 3628800
11!= 39916800
12!= 479001600
13!= 6227020800
14!= 87178291200
15!= 1307674368000
16!= 20922789888000
17!= 355687428096000
18!= 6402373705728000
19!= 121645100408832000
20!= 2432902008176640000
Regards herge