campo-sirio/gfm/dmbyn.asm
alex ba237a9d91 Patch level : no patch
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
Aggiunti i sorgenti per Greenleaf Math Library (gfm.dll)


git-svn-id: svn://10.65.10.50/trunk@10079 c028cbd2-c16b-5b4b-a496-9718f37d4682
2002-02-26 12:19:02 +00:00

327 lines
8.1 KiB
NASM
Executable File

; void _DivUnsArrByUnsArr(c, a, m, b, n, rf)
;
; ARGUMENT
; unsigned a[], b[], c[];
; int m, n;
; int rf;
;
; DESCRIPTION
; Divides an m-word integer a by an n-integer word b, storing the result
; in c. a and b must both be positive, and m >= n. The quotient is
; rounded when rf is set, otherwise is it truncated.
;
; SIDE EFFECTS
; None.
;
; RETURNS
; None.
;
; AUTHOR
; Jared Levy 7/9/89
; Copyright (C) 1989-90 Greenleaf Software Inc. All Rights Reserved.
;
; MODIFICATIONS
;
;
;
include model.h
include prologue.h
include gm.equ
dseg dmbyn
acopm2 dw 1 dup(?)
acop dw 12 dup(?)
diga dw 1 dup(?)
bcopm2 dw 1 dup(?)
bcop dw 6 dup(?)
digb dw 1 dup(?)
digb2 dw 1 dup(?)
digbp1 dw 1 dup(?)
numquot dw 1 dup(?)
firstb dw 1 dup(?)
dstplc dw 1 dup(?)
partpr dw 6 dup (?)
quotdig dw 1 dup(?)
endds
pseg dmbyn
cproc _DivUnsArrByUnsArr,,_dmbyn
; load parameters
if _LDATA
push es
les si, parm6_ ; get source pointer b
mov bx, parm8_ ; get # of digits in b
else
mov ax, ds
mov es, ax
mov si, parm4_ ; get source pointer b
mov bx, parm5_ ; get # of digits in b
endif
; copy b
mov digb, bx ; store # digits of b
mov digbp1, bx
inc digbp1 ; store 1 + # digits of b
sal bx, 1
mov digb2, bx ; store twice # digits of b
mov word ptr bcop[bx], 0 ; store 0 in extra word
loopcb:
dec bx ; next word
dec bx
mov ax, word ptr es:[si+bx] ; copy element of b
mov word ptr bcop[bx], ax
jnz loopcb
if _LDATA
les si, parm3_ ; get source pointer a
mov bx, parm5_ ; get # of digits in a
else
mov si, parm2_ ; get source pointer a
mov bx, parm3_ ; get # of digits in a
endif
; copy a
mov diga, bx ; store # digits of a
sal bx, 1
xor ax, ax
mov acop[bx], ax ; store zero in extra word
loopca:
dec bx ; next word
dec bx
mov ax, word ptr es:[si+bx] ; copy element of a
mov word ptr acop[bx], ax
jnz loopca
; rotate b and a left until high bit of b is set
mov bx, digb2
mov ax, bcopm2[bx] ; get high word of b
mov firstb, ax
rcl ax,1 ; see if high bit set
jc noshift
xor dx,dx
shwb:
xor bx,bx ; start shifting at low digit
mov cx,digb
clc
shblp:
rcl bcop[bx],1 ; rotate digit left
inc bx ; next digit
inc bx
loop shblp
inc dx ; keep track of # of shifts
mov ax, bcopm2[bx] ; get high word of b
rcl ax,1 ; see if high bit set
jnc shwb
mov ax, bcopm2[bx] ; get first digit of b
mov firstb, ax ; & store
shwa:
xor bx,bx ; start shifting at low digit
mov cx,diga
inc cx ; shift extra digit of a
clc
shalp:
rcl acop[bx],1 ; rotate digit left
inc bx ; next digit
inc bx
loop shalp
dec dx
jnz shwa
noshift:
; set up source and destination pointers
if _LDATA
les di, parm1_ ; get destination pointer c
else
mov di, parm1_ ; get destination pointer c
endif
; zero destination
mov bx, 8d
xor ax, ax
zerocl:
mov word ptr es:[di+bx], ax
dec bx
dec bx
jns zerocl
mov ax, diga ; find location to store digits
sub ax, digb ; highest digit stored in word # diga - digb
jns nxtline ; if b has more digits than a, done
jmp done
nxtline:
mov numquot, ax
inc numquot ; compute number of quotient digits
sal ax, 1
add di, ax ; where highest quotient digit stored
mov dstplc, di
mov di, ax ; place to begin first subtraction
mov ax, diga
sal ax, 1
mov si, ax ; place to begin first compare
; if first digit of b is larger than first digit of a,
; first digit of quotient is 0
mov ax, 0
cmp ax, acop[si]
jne firstn0
mov ax, firstb ; get high digit of b
cmp ax, acopm2[si] ; compare to high digit of a
jbe firstn0 ; first quot. digit non-zero
dec numquot ; otherwise, one less quotient digit
jnz nline2 ; if a<b, division done
jmp done
nline2:
jns wordloop
jmp done
wordloop:
dec di ; look at lower digits of a
dec di
dec si ; decrease desination pointer
dec si
dec dstplc
dec dstplc
firstn0:
; finally divide
; divide first digit of b into first two of a
mov dx, acop[si] ; get top 2 remaining words of a
mov ax, 65535d
cmp dx, firstb ; check if first digits of a & b same
je f65535 ; if so, quotient is 65535
mov ax, acopm2[si]
div word ptr firstb ; divide by first digit of b
f65535:
mov quotdig, ax ; store quotient
; multiply b by quotient
; first digit
mul word ptr bcop ; mul low digit
mov partpr, ax ; store partial product
mov bx, 2 ; now second word
clc
pushf ; save carry flag
; middle digits
mullp:
mov cx, dx ; save high word from last mul
mov ax, quotdig ; get quotient
mul bcop[bx] ; mul digit
popf ; restore carry flag
adc ax, cx ; add high word from last mul
pushf ; save carry flag
mov partpr[bx], ax ; store partial product digit
inc bx ; next digit
inc bx
cmp bx, digb2 ; check if done
jl mullp
; last digit
xor ax, ax ; high digit
popf ; restore carry flag
adc ax, dx ; add carry flag
mov partpr[bx], ax ; store high digit
; compare partial product to a
cmplp:
mov ax, word ptr partpr[bx] ; get high word of b
cmp ax, word ptr acop[di+bx] ; compare to high word of a
jb worksout ; if b * q < a, quotient right
ja toolarge ; if b * q > a, quotient too big
dec bx ; if equal compare next digit
dec bx
jns cmplp ; if b=a, compare remaining digits
jmp short worksout ; if exactly equal quotient right
toolarge:
; when quotient too large, decrease quotient & adjust partial product
dec quotdig ; lower quotient by 1
mov bx, 0 ; subtract b from partial prod.
clc
mov cx, digbp1
subtllp:
mov ax, bcop[bx] ; get dig of b
sbb partpr[bx], ax ; subtract from partial prod.
inc bx ; next digit
inc bx
loop subtllp
dec bx ; bx must have right value for cmp
dec bx
jmp short cmplp
worksout:
; store quotient digit
mov bx, dstplc
mov ax, quotdig
mov es:[bx], ax
; subtract number
mov cx, digbp1 ; set counter for number of subtractions
xor bx, bx
clc
sloop:
mov ax, partpr[bx] ; subtract a digit at a time
sbb acop[di+bx], ax
inc bx
inc bx
loop sloop
dec numquot
jz done
jmp wordloop
done:
; handle rounding
if _LDATA
mov ax, parm9_ ; get rounding flag
else
mov ax, parm6_ ; get rounding flag
endif
cmp ax, 0 ; check if rounding flag set
je noround
; see if r >= b/2
mov cx, digbp1
mov si, 0
clc
dloop:
rcl word ptr acop[si], 1 ; double remainder
inc si
inc si
loop dloop
; compare 2*r & b
mov bx, digb2
comrl:
mov ax, acop[bx]
cmp ax, bcop[bx] ; compare digit
ja round ; a>b/2
jb noround ; a<b/2
dec bx
dec bx
jns comrl ; check next digit, round if r = b/2
round:
mov di, dstplc
roundlp:
inc word ptr es:[di]
jnz noround
inc di ; if carry, increment next digit
inc di
jmp short roundlp
noround:
if _LDATA
pop es
endif
cproce
endps
end