; 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