ba237a9d91
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
327 lines
8.1 KiB
NASM
Executable File
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
|