campo-sirio/gfm/mul10l.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

190 lines
4.0 KiB
NASM
Executable File

; int _MulUnsArrByPwrOf10Limited(pa, n, dig);
;
;
; ARGUMENTS
; unsigned *pa[] points to pa[10], a 160 bit number
; (both input and output)
; int n Number of power of ten multiplier 0..19
; int dig Number of digits to multiply
;
; DESCRIPTION
; Multiplies the input in the pa[] array (a 160-bit binary number)
; by 10^n where 0<=n<=19.
; If multiplication overflows, multiplies by largest power of 10
; which doesn't overflow and returns that power of ten.
; The application is in addition when lining up decimal points.
;
; SIDE EFFECTS
; None. (always succeeds)
;
; RETURNS
; Power of ten multiplied by, always <= n.
;
;
; AUTHOR
; Don Killen 14-Jun-1988 15:19:03
; Copyright (C) 1988-90 Greenleaf Software Inc. All Rights Reserved.
;
include model.h
include prologue.h
include gm.equ
dseg mul10l
power dw 1 dup(?) ; power of ten to do
numdig dw 1 dup(?) ; number of nonzero digits
work dw 12 dup (?) ; intermediate result array
hiword dw 1 dup(?) ; byte # of highest word
endds
pseg mul10l
cproc _MulUnsArrByPwrOf10Limited,,_mul10l
if _LDATA
push es
les di,parm1_ ; get pointer to source/destination
mov ax,parm3_ ; get power of 10
mov bx,parm4_ ; get number of digits
else
mov di,parm1_ ; get pointer to source/destination
mov ax,ds
mov es,ax
mov ax,parm2_ ; get power of 10
mov bx,parm3_ ; get number of digits
endif
mov numdig,bx ; store the number of digits
mov power,ax ; store power of 10
shl bx, 1 ; bytes rather than words
mov dx, bx
dec dx ; highest byte # is two less than # of bytes
dec dx
mov hiword, dx ; store location of highest word
;
; Strategy is to multiply by shifting left all 160 bits.
;
; a) Move (parm1) -> work array
; b) shift left work array twice, multiplying by 4
; c) Add (parm1) <= (parm1)+work, multiplying by 5
; d) Shift (parm1) left once, multiplying by 10
; e) Test for overflow (carry out of MSW) each step (jmp to error)
; f) If no error, decrement power & loop to (a) if nonzero.
; g) When power has been decremented to 0, you're done!
;
;
; Top of main loop, repeat from here 'power' times.
;
lp0: ; top of major loop.
;
; Transfer the source to the work array. Work from msd down to lsd
;
if _LDATA
les di,parm1_
else
mov di,parm1_
endif
mov ax, 3276d ; if high word >= 3276,
mov bx, hiword ; can't multiply any more
cmp ax, word ptr es:[di+bx]
jg canmul ; can multiply
if _LDATA ; No more mul's possible
mov ax, parm3_ ; From total multiplications,
else
mov ax, parm2_
endif
sub ax, power ; Subtract remaining mul's
jmp short overflow ; to return number of mul's
canmul:
mov si,0 ; move msd first
mov cx,numdig
lp2: mov ax,word ptr es:[di] ; load source word
mov word ptr work[si],ax ; store in 'work'
inc si
inc si
inc di
inc di
loop lp2 ; til done.
;
; Shift the work array left two bits.
;
mov cx,numdig ; loop count
mov si,0 ; index into work array
clc
lp4: rcl word ptr work[si],1 ; rotate with carry
inc si
inc si
loop lp4 ; complete 1st shift (x2)
mov cx,numdig
mov si,0
clc
lp5: rcl word ptr work[si],1 ; rotate with carry
inc si
inc si
loop lp5 ; complete 2nd shift (x4)
;
; So far, work=pa*4.
;
; Add pa=pa+work, making pa=pa*5
;
if _LDATA
les di,parm1_ ; get pointer to source/destination
else
mov di,parm1_ ; get pointer to source/destination
endif
mov cx,numdig
mov si,0
clc
lp6: mov ax,word ptr work[si]
adc word ptr es:[di],ax
inc di
inc di
inc si
inc si
loop lp6 ; Added orig array to 4x: (x5)
;
;
; At this point, pa=pa*5. Now shift it left making pa=pa*10
;
if _LDATA
les di,parm1_
else
mov di,parm1_
endif
mov cx,numdig
clc
lp7: rcl word ptr es:[di],1 ; rotate left to shift with carry.
inc di
inc di
loop lp7 ; Multiplied (x5) by 2 making (x10) in src
; Code deleted 1/15/90 MRN
;
; If no overflow has occurred, decrement power counter and loop
; through entire x10 routine.
;
dpow: dec power
jz mcomplete
jmp lp0 ; major loop
mcomplete:
if _LDATA
mov ax, parm3_ ; did all requested multiplications
else
mov ax, parm2_
endif
overflow:
if _LDATA
pop es
endif
cproce
endps
end