home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
asmutl
/
bluebook.arc
/
MULTIDGT.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-05-11
|
8KB
|
301 lines
COMMENT ~
MULTIDGT.ASM -- Multidigit Arithmetic Procedures
From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
by Christopher L. Morgan
Copyright (C) 1984 by The Waite Group, Inc.
Purpose: These routines perform addition, subtraction, multiplication,
and division upon multidigit integers (16-bit).
Contents:
---------
MBINADD -- Multidigit binary addition
MBINDIV -- Multidigit binary division
MBINMUL -- Multidigit binary multiplication
MBINSUB -- Multidigit binary subtraction
>>>> See MULTIDGT.DOC for complete descriptions of these routines. <<<<<
_____________________________________________________________________________
~
EXTRN STDIN:FAR,STDOUT:FAR
;______________________________________________________________________________
;
; Needs a constant named ISIZE
DATAS SEGMENT PUBLIC
TBUFF DB 5 DUP(?)
DATAS ENDS
;______________________________________________________________________________
;
CODES SEGMENT
PUBLIC MBINADD,MBINSUB,MBINMUL,MBINDIV
ASSUME CS:CODES,DS:DATAS
;____________________________I/O ROUTINES______________________________________
;
MBINADD
;Routine to add multidigit binary numbers
;
MBINADD PROC FAR
PUSH SI ;Save registers
PUSH DI
PUSH BX
PUSH CX
PUSH AX
MOV CX,ISIZE ;Get the # of 16-bit "digits"
CLC ;Clear the carry in
MBINADD1:
MOV AX,[SI] ;Get "digit" from first number
INC SI ;Point to next "digit"
INC SI
ADC AX,[DI] ;Add "digit" from second num
INC DI ;Point to next "digit"
INC DI ;Move resulting
MOV [BX],AX ; "digit" into place
INC BX ;Point to next "digit"
INC BX
LOOP MBINADD1 ;Loop through all "digits"
POP AX ;Restore registers
POP CX
POP BX
POP DI
POP SI
RET
MBINADD ENDP
;______________________________________________________________________________
;Routine to subtract multidigit binary numbers
;
MBINSUB PROC FAR
PUSH SI ;Save registers
PUSH DI
PUSH BX
PUSH CX
PUSH AX
MOV CX,ISIZE ;Get the # of 16-bit "digits"
CLC ;Clear the carry in
MBINSUB1:
MOV AX,[DI] ;Get "digit" from second num
INC DI ;Point to next "digit"
INC DI
SBB AX,[SI] ;Subtract "digit" of first num
INC SI ;Point to next "digit"
INC SI ;Move resulting
MOV [BX],AX ; "digit" into place
INC BX ;Point to next "digit"
INC BX
LOOP MBINADD1 ;Loop through all "digits"
POP AX ;Restore registers
POP CX
POP BX
POP DI
POP SI
RET
MBINSUB ENDP
;______________________________________________________________________________
;Routine to multiply multidigit binary numbers
;
MBINMUL PROC FAR
PUSH SI ;Save registers
PUSH DI
PUSH BX
PUSH CX
PUSH AX
;
;Clear result buffer
PUSH BX ;Save result pointer BX
MOV AX,0 ;Get a zero
MOV CX,2*ISIZE ;Double precision for this num
CLD ;Forward direction
MBINMUL1:
MOV [BX],AX ;Clear the "digit"
INC BX ;Point to next "digit"
INC BX
LOOP MBINMUL1 ;Loop through all "digits"
POP BX ;Restore result pointer BX
MOV CX,ISIZE ;Get the num of 16-bit "digits"
MBINMUL2:
PUSH CX ;Save outer loop count
MOV DX,[SI] ;Get "digit" from first number
INC SI ;Point to next "digit"
INC SI
PUSH BX ;Save regs during inner loop
PUSH DI
MOV CX,ISIZE ;Get the num of 16-bit "digits"
MBINMUL3:
PUSH CX ;Save inner loop count
PUSH DX ;Save multiplier "digit"
MOV AX,[DI] ;Get "digit" from second num
INC DI ;Point to next "digit"
INC DI
MUL DX ;Multiply
ADD [BX],AX ;Add lower "digit" to result
INC BX ;Point to next "digit"
INC BX
ADC [BX],DX ;Add upper part to result
POP DX ;Restore multiplier
POP CX ;Restore inner loop count
LOOP MBINMUL3 ;Loop through all "digits" of
; second
POP DI ;Restore registers
POP BX
INC BX ;Shift by one "digit"
INC BX
POP CX ;Restore outer loop count
LOOP MBINMUL3 ;Loop through all "digits" of
; first
POP AX ;Restore registers
POP CX
POP BX
POP DI
POP SI
RET
MBINMUL ENDP
;______________________________________________________________________________
;Routine to divide multidigit binary numbers
; This routine uses 4 local subroutines: DIVCMP,DIVSAL,DIVSLR,DIVSUB,QUOTSHL
;
;---------------------------LOCAL SUBROUTINES----------------------------------
;Local subroutine to compare divisor against dividend
;
DIVCMP PROC NEAR
PUSH SI ;Save registers
PUSH DI
PUSH CX
STD ;Backward direction
ADD SI,4*ISIZE-2 ;Point to end of temp divisor
ADD DI,4*ISIZE-2 ;Point to end of quotient
MOV CX,2*ISIZE ;Count for double precision
REPZ CMPSW ;Compare "digit" by "digit"
POP CX ;Restore registers
POP DI
POP SI
RET
DIVCMP ENDP
;------------------------------------------------------------------------------
;Local subroutine to arithmetically shift divisor left
;
DIVSAL PROC NEAR
PUSH SI ;Save registers
PUSH CX
MOV CX,2*ISIZE ;Set counter
CLC ;Clear carry in
DIVSAL1:
RCL WORD PTR [SI],1 ;Shift one word by one bit
INC SI ;Point to next word
INC SI
LOOP DIVSAL1 ;Loop through entire divisor
POP CX ;Restore registers
POP SI
RET
DIVSAL ENDP
;------------------------------------------------------------------------------
;Local subroutine to logically shift divisor right
;
DIVSLR PROC NEAR
PUSH SI ;Save registers
PUSH CX
ADD SI,4*ISIZE-2 ;Point to end of temp divisor
MOV CX,2*ISIZE ;Count for double precision
CLC ;Clear carry in
DIVSLR1:
RCR WORD PTR [SI],1 ;Rotate one word by one bit
DEC SI ;Point to next word
DEC SI
LOOP DIVSLR1 ;Loop through entire divisor
POP CX ;Restore registers
POP SI
RET
DIVSLR ENDP
;------------------------------------------------------------------------------
;Local subroutine to subtract shifted divisor from divident
;
DIVSUB PROC NEAR
PUSH SI ;Save registers
PUSH DI
PUSH CX
CLC ;Cleary carry in
MOV CX,2*ISIZE ;Set count for double precision
DIVSUB1:
MOV AX,[SI] ;Get word from shifted divisor
INC SI ;Point to next word
INC SI
SBB [DI],AX ;Subtract from word of dividend
INC DI ;Point to next word
INC DI
LOOP DIVSUB1 ;Loop through all words
POP CX ;Restore registers
POP DI
POP SI
RET
DIVSUB ENDP
;------------------------------------------------------------------------------
;Local subroutine to shift quotient left
;
QUOTSHL PROC NEAR
PUSH BX ;Save registers
PUSH CX
MOV CX,ISIZE ;Count for single precision
QUOTSHL1:
RCL WORD PTR [BX],1 ;Shift wrd of quotnt left once
INC BX ;Point to next word
INC BX
LOOP QUOTSHL1 ;Loop through entire quotient
POP CX ;Restore registers
POP BX
RET
DIVSHL ENDP
;------------------------------------------------------------------------------
; >>>>> End of Local Subroutines
;
;Routine to divide multidigit binary numbers
;
MBINDIV PROC FAR
PUSH SI ;Save registers
PUSH DI
PUSH BX
PUSH CX
PUSH AX
;
;Put single precision divisor into double precision location
PUSH DI ;Save dividend pointer
LEA DI,TEMPDIV ;Point SI to temporary divisor
MOV CX,1 ;Initialize shift count to 1
;
;Normalize divisor
MBINDIV1:
TEST MSBDIV,8000H ;Test MSB of divisor
JNZ MBINDIV2 ;Exit if normalized
CALL DIVSAL ;Arith shift left, if not
INC CX ;Count the shift
JMP MBINDIV1 ;Keep looping till normalized
;
;Compare, subtract, shift loop
MBINDIV2:
CALL DIVCMP ;Compare divisor with dividend
JA MBINDIV3 ;Skip if too large
CALL DIVSUB ;Else subtract
STC ;New bit of quotient is in 1
JMP MBINDIV4 ;Jump to end of loop
MBINDIV3:
CLC ;New bit of quotient is in 0
MBINDIV4:
CALL QUOTSHL ;Shift bit into the quotient
CALL DIVSLR ;Logic shift divisor right once
LOOP MBINDIV2 ;Loop for next digit
POP AX ;Restore registers
POP CX
POP BX
POP DI
POP SI
RET
MBINDIV ENDP
;______________________________________________________________________________
CODES ENDS
;
END
;______________________________________________________________________________
;>>>>> Physical EOF MULTIDGT.ASM <<<<<