home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
asm
/
wasm
/
factor.asm
< prev
next >
Wrap
Assembly Source File
|
1987-11-26
|
10KB
|
448 lines
Title 'Wolfware Assembler Sample Program', 'Factorial Calculator'
;=============================================================================
; Factorial Calculator
;
; This a program to display the factorial of numbers. Once assembled, to
; run, just type:
;
; FACTOR
;
; Incidentally, the factorial of a number is the product of all integers
; between the number and zero. For instance, the factorial of 6 (usually
; specified as 6!) is equal to 6 x 5 x 4 x 3 x 2 x 1 = 720. If the result
; is too large, an error message will be displayed.
;
; Requires CONVERT1.INC and CONVERT2.INC on the default drive/path for
; assembly.
MaxChr Equ 40 ;input characters
Fninit
Mov Dx, Offset Mess1 ;opening display
Mov Ah, 9
Int 21h ;display string
Main1
Mov Dx, Offset Mess2 ;prompt for number
Call Input_Integer ;get an integer
Jc Main3 ;jump if done
Call Factorial ;calculate factorial
Jc Main2 ;jump if error
Call Save_Binary ;store number, return exponent in AX
Push Ax
Mov Ah, 9
Mov Dx, Offset Mess3 ;result message
Int 21h ;display string
Pop Ax
Call Display_Binary ;display
Jmps Main1
;--- error in calculation
Main2
Mov Ah, 9
Mov Dx, Offset Mess4 ;result message
Int 21h ;display string
Jmps Main1
;--- finished
Main3
Mov Ax, 4c00h
Int 21h
;--- messages
Mess1 Db 13,10,'Factorial Calculator, Version 1.00',13,10,'$'
Mess2 Db 13,10,'Enter number for factorial calculation: $'
Mess3 Db 13,10,'The factorial is $'
Mess4 Db 13,10,'The factorial cannot be calculated',13,10,'$'
;========================================
; Calculate the factorial of the number
; in ST. If error, the carry is set and
; the 8087 stack is cleared.
Factorial Proc Near
Push Bp
Sub Sp, 2 ;local data
Mov Bp, Sp
Fld1 ;load one, initial total
Fxch ;total in second stack element
;--- loop while number is not zero
Factor1
Ftst ;check if top element zero
Fstsw Word [Bp] ;store the status word
Fwait
Mov Al, [Bp+1] ;get the high byte
And Al, 45h ;mask condition codes C3 C2 and C0
Cmp Al, 40h ;check if zero
Je Factor2
Fmul St(1), St(0) ;multiply
Fstsw Word [Bp] ;store the status word
Fwait
Test Byte [Bp], 1fh ;check if any exceptions
Jnz Factor3
Fld1 ;load one
Fsub ;subtract and pop
Jmps Factor1
;--- finished
Factor2
Fstp St(0) ;pop stack
Add Sp, 2
Pop Bp
Clc
Ret
;--- exception occured
Factor3
Fstp St(0)
Fstp St(0) ;clear stack
Fclex ;clear exceptions
Add Sp, 2
Pop Bp
Stc
Ret
Endp ;Factorial
;========================================
; Display the $ terminated string at DX
; and then input an integer and return it
; in ST. Carry set if no input. All
; non-numeric characters are ignored.
Input_Integer Proc Near
Pushf
Push Bp
Sub Sp, MaxChr+3 ;local data, room for input
Mov Bp, Sp
Inpint1
Mov Ah, 9
Int 21h ;display string
Push Dx
Mov Byte [Bp], MaxChr+1 ;possible number of characters (plus CR)
Lea Dx, [Bp] ;get the location
Mov Ah, 0ah
Int 21h ;input string
Call New_Line ;start a new line
Pop Dx
Mov Al, [Bp+1] ;get the input length
Or Al, Al
Jz Inpint6 ;jump if none
Push Dx
;--- store digits
Std ;set direction
Lea Si, [Bp+1] ;get start of input minus one
Sub Ah, Ah
Add Si, Ax ;point to last (low) digit
Sub Bx, Bx ;counts digits
Mov Cx, Ax ;character count
Call Init_Binary ;initialize BCD number
Inpint2
Lodsb ;get digit
Sub Al, '0' ;convert to binary
Jb Inpint3 ;jump if too low
Cmp Al, 9 ;check if too high
Ja Inpint3 ;jump if so
Inc Bx
Call Store_Binary ;store BCD digit
Inpint3 Loop Inpint2
;--- store zeros
Mov Cx, 18 ;max digits
Sub Cx, Bx ;get difference
Jbe Inpint5 ;jump if full (no padding)
Inpint4
Sub Al, Al ;zero digit
Call Store_Binary ;store pad digit
Loop Inpint4 ;loop for count
;--- number stored
Inpint5
Call Load_Binary ;put number in ST
Pop Dx
Jc Inpint7
Add Sp, MaxChr+3
Pop Bp
Popf
Clc
Ret
;--- no input
Inpint6
Add Sp, MaxChr+3
Pop Bp
Popf
Stc
Ret
;--- illegal number, should never happen if only valid digits are read
Inpint7
Push Dx
Mov Dx, Offset Inperr ;error message
Mov Ah, 9
Int 21h ;display string
Pop Dx
Jmp Inpint1
Inperr Db 13,10,'Error in number',13,10,'$'
Endp ;Input_Integer
;========================================
; Global BCD data.
BCD_Flag Db ?
BCD_Store Db ?
BCD_Count Dw ?
BCD_Number Label Tbyte
Ds 10
;========================================
; Initialize the global BCD number.
Init_Binary Proc Near
Mov BCD_Flag, 0 ;clear flag
Mov BCD_Count, 0 ;clear byte count
Mov Byte BCD_Number+9, 0 ;clear sign (always positive)
Ret
Endp ;Init_Binary
;========================================
; Store the digit in AL to the BCD
; number.
Store_Binary Proc Near
Push Bx
Test BCD_Flag, 1 ;check if second digit
Jnz Stobin1
;--- wait for second digit
Mov BCD_Store, Al ;save digit
Jmps Stobin2
;--- store digit pair
Stobin1
Mov Bx, BCD_Count ;get digit count
Cmp Bx, 9 ;check if count exceeded
Jae Stobin3
Shl Al
Shl Al
Shl Al
Shl Al
Or Al, BCD_Store ;combine other digit
Add Bx, Offset BCD_Number ;get location
Mov [Bx], Al ;save digit
Inc BCD_Count ;increment digit count
;--- finished
Stobin2
Xor BCD_Flag, 1 ;flip flag
Stobin3
Pop Bx
Ret
Endp ;Store_Binary
;========================================
; Load the BCD number to ST. Carry is
; set if illegal number. Since the
; number reading routine skips non-digit
; characters, ALL input numbers should
; be valid (i.e. legal).
Load_Binary Proc Near
Push Bp
Sub Sp, 2 ;local data
Mov Bp, Sp
Fbld BCD_Number ;load number
Fxam ;examine
Fstsw Word [Bp] ;store the status word
Fwait
Mov Al, [Bp+1] ;get the high byte
And Al, 47h ;mask all condition codes
Cmp Al, 04h ;check if +Normal
Je Lodbin1
Cmp Al, 40h ;check if +0
Je Lodbin1
Add Sp, 2
Pop Bp
Stc
Ret
Lodbin1
Add Sp, 2
Pop Bp
Clc
Ret
Endp ;Load_Binary
;========================================
; Store the number in ST to the BCD
; number. The base ten exponent is
; returned in AX
Save_Binary Proc Near
Mov Ax, 40 ;significant binary digits
Call Flt2dec ;convert floating point to integer
Fbstp BCD_Number ;store the integer
Ret
Endp ;Save_Binary
;========================================
; Display the BCD number with an exponent
; in AX. Assume positive number.
Display_Binary Proc Near
Push Bp
Sub Sp, 6
Mov Bp, Sp
;--- display digits
Pushf
Mov Cx, 18 ;maximum digit count
Cmp Ax, 0 ;check if negative exponent
Jge Disbin1 ;jump if not
Add Cx, Ax ;get real digit count
Sub Ax, Ax ;no exponent any more
Disbin1
Push Ax
Std ;reverse direction, last byte to first
Mov Dh, Cl ;set digit count
Sub Dl, Dl ;preceding zero flag
Mov Cx, 9 ;byte count
Mov Si, Offset BCD_Number + 8 ;last digit location
Disbin2
Lodsb ;load byte
Push Ax
Shr Al
Shr Al
Shr Al
Shr Al
Call Display_Dig ;display digit
Pop Ax
And Al, 0fh ;mask bits
Call Display_Dig ;display digit
Loop Disbin2
;--- show exponent (assume positive value)
Pop Ax
Popf
Or Ax, Ax ;check if none
Jz Disbin4
Mov Cx, 10 ;number base
Sub Dx, Dx ;high word of exponent
Lea Di, [Bp] ;place to put number string
Call Convert_Num ;convert number
Mov Ah, 9 ;function
Mov Dx, Offset Expmes ;exponent message
Int 21h ;display
Mov Dx, 0ff00h ;set digit count and preceding zero flag
Mov Si, Di ;location of number
Disbin3
Lodsb ;load digit
Or Al, Al ;check if finished
Jz Disbin4
Sub Al, '0' ;make binary digit
Call Display_Dig ;display digit
Jmps Disbin3
Disbin4
Call New_Line ;new display line
Add Sp, 6
Pop Bp
Ret
Expmes Db ' x 10^$'
Endp ;Display_Binary
;========================================
; Display the digit in AL. DH= count of
; digits to left of decimal point (if
; DH=0, no display). DL= preceding
; zero flag (if DL = 0, zero will be
; skipped).
Display_Dig Proc Near
Or Dh, Dh ;check digit count
Jz Disdig2
Dec Dh ;reduce count
Or Al, Al ;check if zero
Jnz Disdig1
Or Dl, Dl ;check zero flag
Jz Disdig2
Disdig1
Push Dx
Add Al, '0' ;make ASCII digit
Call Display_Char ;display
Pop Dx
Mov Dl, 1 ;set flag, non-zero digit
Disdig2 Ret
Endp ;Display_Dig
;========================================
; Start a new display line.
New_Line Proc Near
Mov Al, 13
Call Display_Char ;display digit
Mov Al, 10
Call Display_Char ;display digit
Ret
Endp
;========================================
; Display the character in AL.
Display_Char Proc Near
Mov Dl, Al ;load character
Mov Ah, 2 ;function number
Int 21h ;display
Ret
Endp
;========================================
; External source files.
Include 'Convert1.Inc'
Include 'Convert2.Inc'