191 lines
4.0 KiB
NASM
191 lines
4.0 KiB
NASM
|
; int _DivUnsArrByPwrOf10(a, n, p)
|
||
|
;
|
||
|
; ARGUMENT
|
||
|
; unsigned a[] n-word number to divide
|
||
|
; int n number of digits
|
||
|
; int p power of 10 to divide by
|
||
|
;
|
||
|
; DESCRIPTION
|
||
|
; Divides a n-word 'a' by a power of 10, c = a / 10^p,
|
||
|
; a>=0, p>0, rounding the result. c is correct only if a / 10^p < 2^79.
|
||
|
;
|
||
|
; SIDE EFFECTS
|
||
|
; The value of a is destroyed (it isn't needed later).
|
||
|
;
|
||
|
; RETURNS
|
||
|
; None. (always succeeds)
|
||
|
;
|
||
|
; 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 dmbyp10
|
||
|
p10 dw 1d,10d,100d,1000d,10000d
|
||
|
endds
|
||
|
|
||
|
pseg dmbyp10
|
||
|
cproc _DivUnsArrByPwrOf10,,_dmbyp10
|
||
|
|
||
|
; load parameters
|
||
|
|
||
|
if _LDATA
|
||
|
mov ax, parm4_ ; get power of 10 to divide by
|
||
|
else
|
||
|
mov ax, parm3_ ; get power of 10 to divide by
|
||
|
endif
|
||
|
|
||
|
cmp ax, 0 ; if dividing by 10^0=1,
|
||
|
je qexit ; nothing need be done
|
||
|
|
||
|
if _LDATA
|
||
|
push es
|
||
|
les di, parm1_ ; get pointer to source & destination
|
||
|
mov bx, parm3_ ; get number of digits
|
||
|
else
|
||
|
mov di, parm1_ ; get pointer to source & destination
|
||
|
mov dx, ds
|
||
|
mov es, dx
|
||
|
mov bx, parm2_ ; get number of digits
|
||
|
endif
|
||
|
|
||
|
cmp ax, 4 ; Is the division by less than 10^4?
|
||
|
jle less4d
|
||
|
|
||
|
d10000:
|
||
|
mov cx, 10000d ; divide by 10000=10^4
|
||
|
d4loop:
|
||
|
push ax ; save ax & bx
|
||
|
push bx
|
||
|
call near ptr dmby1a3 ; division
|
||
|
pop bx ; restore ax & bx
|
||
|
pop ax
|
||
|
sub ax, 4 ; 4 less powers of 10 to divide by
|
||
|
cmp ax, 4 ; are there 4 more left to do?
|
||
|
jg d4loop ; yes, do it again
|
||
|
|
||
|
less4d:
|
||
|
mov si, ax
|
||
|
sal si, 1
|
||
|
mov cx, p10[si] ; load correct power of ten
|
||
|
call near ptr dmby1ra3 ; division, with rounding
|
||
|
|
||
|
if _LDATA
|
||
|
pop es
|
||
|
endif
|
||
|
qexit:
|
||
|
cproce
|
||
|
|
||
|
dmby1a3:
|
||
|
dec bx ; digits go from 0 to n-1
|
||
|
sal bx, 1 ; want bytes rather than words
|
||
|
|
||
|
;/* skip initial zeroes */
|
||
|
; for(;(q>0)&&(c[q-1]==0);q--);
|
||
|
;
|
||
|
; if (q == 0)
|
||
|
; return(0);
|
||
|
; q--; /* q will be used for subscript */
|
||
|
zeroloop:
|
||
|
mov ax, word ptr es:[di+bx] ; get digit
|
||
|
cmp ax, 0 ; is digit zero?
|
||
|
jne nonzero ; if non-zero, begin divide
|
||
|
dec bx ; next word
|
||
|
dec bx
|
||
|
cmp bx, 0 ; last digit?
|
||
|
jge zeroloop ; if not, process next digit
|
||
|
xor ax, ax ; otherwise, remainder 0
|
||
|
jmp short exit1 ; && division through (0/c=0)
|
||
|
|
||
|
; bl = (unsigned long) b;
|
||
|
; while (q>=0) {
|
||
|
; k = (unsigned long *) &r[q];
|
||
|
; cl = *k / bl;
|
||
|
; c[q] = (unsigned) cl;
|
||
|
; r[q] = (unsigned) (*k - cl * bl);
|
||
|
; q--;
|
||
|
; }
|
||
|
nonzero:
|
||
|
xor dx,dx ; high word zero in first divide
|
||
|
divloop:
|
||
|
div cx ; divide digit
|
||
|
mov word ptr es:[di+bx], ax ; store quotient digit
|
||
|
cmp bx, 0 ; last digit?
|
||
|
je exit2 ; if so, division complete
|
||
|
dec bx ; next digit
|
||
|
dec bx
|
||
|
mov ax, word ptr es:[di+bx] ; get digit
|
||
|
jmp short divloop ; process digit
|
||
|
|
||
|
exit2:
|
||
|
mov ax, dx ; return remainder
|
||
|
exit1:
|
||
|
ret
|
||
|
|
||
|
dmby1ra3:
|
||
|
dec bx ; digits go from 0 to n-1
|
||
|
sal bx, 1 ; want bytes rather than words
|
||
|
|
||
|
;/* skip initial zeroes */
|
||
|
; for(;(q>0)&&(c[q-1]==0);q--);
|
||
|
;
|
||
|
; if (q == 0)
|
||
|
; return(0);
|
||
|
; q--; /* q will be used for subscript */
|
||
|
rzeroloop:
|
||
|
mov ax, word ptr es:[di+bx] ; get digit
|
||
|
cmp ax, 0 ; is digit zero?
|
||
|
jne rnonzero ; if non-zero, begin divide
|
||
|
dec bx ; next word
|
||
|
dec bx
|
||
|
cmp bx, 0 ; last digit?
|
||
|
jge rzeroloop ; if not, process next digit
|
||
|
; xor ax, ax ; otherwise, remainder 0
|
||
|
jmp short rexit1 ; && division through (0/c=0)
|
||
|
|
||
|
; bl = (unsigned long) b;
|
||
|
; while (q>=0) {
|
||
|
; k = (unsigned long *) &r[q];
|
||
|
; cl = *k / bl;
|
||
|
; c[q] = (unsigned) cl;
|
||
|
; r[q] = (unsigned) (*k - cl * bl);
|
||
|
; q--;
|
||
|
; }
|
||
|
rnonzero:
|
||
|
xor dx,dx ; high word zero in first divide
|
||
|
rdivloop:
|
||
|
div cx ; divide digit
|
||
|
mov word ptr es:[di+bx], ax ; store quotient digit
|
||
|
cmp bx, 0 ; last digit?
|
||
|
je rexit2 ; if so, division complete
|
||
|
dec bx ; next digit
|
||
|
dec bx
|
||
|
mov ax, word ptr es:[di+bx] ; get digit
|
||
|
jmp short rdivloop ; process digit
|
||
|
|
||
|
; round up if remainder > (divisor-1)/2
|
||
|
rexit2:
|
||
|
dec cx ; set cx = (cx-1)/2
|
||
|
sar cx, 1
|
||
|
cmp dx, cx ; test for rounding up
|
||
|
ja inclp ; if remainder is large, round up
|
||
|
ret
|
||
|
inclp:
|
||
|
inc word ptr es:[di]
|
||
|
jnz rexit1
|
||
|
inc di
|
||
|
inc di
|
||
|
jmp short inclp
|
||
|
|
||
|
rexit1:
|
||
|
ret
|
||
|
endps
|
||
|
end
|