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
		
			
				
	
	
		
			323 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			NASM
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			323 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			NASM
		
	
	
		
			Executable File
		
	
	
	
	
 ; int  _MulUnsArrP10AndAddInt(pa,c);
 | 
						|
 ;
 | 
						|
 ; ARGUMENT
 | 
						|
 ;      unsigned        *pa     points to a pa[5], or 80-bit number
 | 
						|
 ;      int             c       # to add after mult by 10
 | 
						|
 ;
 | 
						|
 ; DESCRIPTION
 | 
						|
 ;      multiplies the number (<=80-bits) in the int array by decimal 10
 | 
						|
 ;  and adds 'c' to it. Used in the divide routines for adjusting
 | 
						|
 ;  the result.
 | 
						|
 ;
 | 
						|
 ; SIDE EFFECTS
 | 
						|
 ;      The value in the source array is indeterminate on overflow.
 | 
						|
 ;
 | 
						|
 ; RETURNS
 | 
						|
 ;      Returns GM_OVERFLOW on overflow, otherwise GM_SUCCESS.
 | 
						|
 ;
 | 
						|
 ; AUTHOR
 | 
						|
 ;  Andy Anderson   27-JUL-87   80-bit
 | 
						|
 ;   Copyright (C) 1987-90 Greenleaf Software Inc.  All Rights Reserved.
 | 
						|
 ;
 | 
						|
 ; MODIFICATIONS
 | 
						|
 ;
 | 
						|
 ;
 | 
						|
        .SFCOND
 | 
						|
 | 
						|
        include model.h
 | 
						|
        include prologue.h
 | 
						|
        include gm.equ
 | 
						|
 | 
						|
        ReferVar        wGMTemp1,<cWord>
 | 
						|
        ReferVar        wrgGMPartProd,<cWord>
 | 
						|
 | 
						|
        dseg    _gm
 | 
						|
        endds
 | 
						|
 | 
						|
        pseg    gmath
 | 
						|
;
 | 
						|
;  if large memory model then:
 | 
						|
;
 | 
						|
;       parm1_ = ptr to source 1
 | 
						|
;       parm3_ = number to add to a*10
 | 
						|
;
 | 
						|
;  for if small model then
 | 
						|
;       parm1_ = ptr to source1
 | 
						|
;       parm2_ = number to add to result of a * 10
 | 
						|
;
 | 
						|
 | 
						|
        cproc   _MulUnsArrP10AndAddInt,,_mul10ad
 | 
						|
 | 
						|
if      _LDATA
 | 
						|
        push    ds
 | 
						|
        push    es
 | 
						|
        lds     si,parm1_       ; ptr to dst (=src)
 | 
						|
else
 | 
						|
        mov     si,parm1_
 | 
						|
endif
 | 
						|
;
 | 
						|
;       to multiply by 10, we mult by 4 using 2 shifts, add the
 | 
						|
;  original number making 5 times the original, then multiply
 | 
						|
;  that by 2 giving a multiplication by 10. This is many times
 | 
						|
;  FASTER than the mul instruction!!!
 | 
						|
;
 | 
						|
 | 
						|
        mov     ax,[si+8]       ; get msd for possible overflow
 | 
						|
        cmp     ax,3000h        ; overflow if sign sets during the
 | 
						|
        jl      nxt             ;  first shift set
 | 
						|
        jmp     overf
 | 
						|
nxt:    cmp     ax,0bffh        ;  if < this, no overflow possible
 | 
						|
        jl      ct              ; no possibility of overflow
 | 
						|
        jmp     tstover         ; further testing needed
 | 
						|
ct:     xor     ax,ax           ;  start clear for test
 | 
						|
        mov     bx,8            ; offset to last int
 | 
						|
        mov     cx,5            ; max number of ints in 80-bit value
 | 
						|
numints:
 | 
						|
        or      ax,[bx+si]      ; see if upper 80 bits are set
 | 
						|
        jnz     gotdig          ;  and stop when first one seen
 | 
						|
        dec     bx
 | 
						|
        dec     bx
 | 
						|
        loop    numints         ;  if we find all of them zero
 | 
						|
if      _LDATA
 | 
						|
        mov     ax,parm3_
 | 
						|
else
 | 
						|
        mov     ax,parm2_
 | 
						|
endif
 | 
						|
        mov     [si],ax         ; just put it in low-order word
 | 
						|
        jmp     gexit
 | 
						|
gotdig:
 | 
						|
ifdef   DSNOTHING
 | 
						|
        push    ds
 | 
						|
        mov     ax, seg wGMTemp1
 | 
						|
        mov     ds,ax
 | 
						|
        mov     wGMTemp1,cx     ; save # of digits in source
 | 
						|
        pop     ds
 | 
						|
else
 | 
						|
        mov     wGMTemp1,cx     ; save # of digits in source
 | 
						|
endif
 | 
						|
;
 | 
						|
;       then shift the number of ints figured for each loop
 | 
						|
;
 | 
						|
ifdef   DSNOTHING
 | 
						|
        mov     ax, seg wrgGMPartProd
 | 
						|
        mov     es,ax
 | 
						|
endif
 | 
						|
        lea     di,wrgGMPartProd  ; ptr to work area
 | 
						|
 | 
						|
        xor     bx,bx
 | 
						|
        mov     dx,bx
 | 
						|
shlp:
 | 
						|
        mov     ax,[bx+si]      ; do 16-bits at a time
 | 
						|
        clc
 | 
						|
        rcl     dx,1            ;  dummy first time thru
 | 
						|
        rcl     ax,1            ;  multiply by 2
 | 
						|
        rcl     dx,1            ;  save carry in dh (d1-d0)
 | 
						|
        rcl     ax,1            ;  now original * 4
 | 
						|
        rcl     dx,1            ;  and dx has shifted out bits
 | 
						|
ifdef   DSNOTHING
 | 
						|
        mov     es:[bx+di],ax   ; store temp result
 | 
						|
else
 | 
						|
        mov     [bx+di],ax      ; store temp result
 | 
						|
endif
 | 
						|
        ror     dx,1
 | 
						|
        ror     dx,1
 | 
						|
        inc     bx
 | 
						|
        inc     bx
 | 
						|
        loop    shlp
 | 
						|
;
 | 
						|
;       if we have bits shifted out into dx left over, then
 | 
						|
;  we have gained 1 int.  This is overflow if we were already
 | 
						|
;  doing 5 int's!
 | 
						|
;
 | 
						|
 | 
						|
        or      dx,0000h        ;  was max size number, if dx!=0
 | 
						|
        jz      addin           ; no bits shifted into carry
 | 
						|
ifdef   DSNOTHING
 | 
						|
        push    ds
 | 
						|
        mov     ax,seg wGMTemp1
 | 
						|
        mov     ds,ax
 | 
						|
        inc     wGMTemp1        ;  otherwise, one more int in number
 | 
						|
        pop     ds
 | 
						|
else
 | 
						|
        inc     wGMTemp1        ;  otherwise, one more int in number
 | 
						|
endif
 | 
						|
        rol     dx,1            ; bits to low-order of next msd
 | 
						|
        rol     dx,1            ; in lifo order
 | 
						|
ifdef   DSNOTHING
 | 
						|
        mov     es:[bx+di],dx
 | 
						|
else
 | 
						|
        mov     [bx+di],dx
 | 
						|
endif
 | 
						|
;
 | 
						|
;       Then add the original for sum of 5 X original
 | 
						|
;
 | 
						|
addin:  xor     bx,bx
 | 
						|
        mov     dx,bx
 | 
						|
ifdef   DSNOTHING
 | 
						|
        push    ds
 | 
						|
        mov     ax, seg wGMTemp1
 | 
						|
        mov     ds,ax
 | 
						|
        mov     cx,wGMTemp1     ; k int's in new number
 | 
						|
        pop     ds
 | 
						|
else
 | 
						|
        mov     cx,wGMTemp1     ; k int's in new number
 | 
						|
endif
 | 
						|
        clc
 | 
						|
 | 
						|
if      _LDATA
 | 
						|
        les     di,parm1_
 | 
						|
else
 | 
						|
        mov     di,parm1_
 | 
						|
endif
 | 
						|
ifdef   DSNOTHING
 | 
						|
        mov     ds,ax           ; scrap old DS, get global one
 | 
						|
endif
 | 
						|
        lea     si,wrgGMPartProd
 | 
						|
 | 
						|
addlp:
 | 
						|
if      _LDATA
 | 
						|
        mov     ax,[bx+si]      ; do 16-bits at a time
 | 
						|
        adc     es:[bx+di],ax
 | 
						|
else
 | 
						|
        mov     ax,[bx+si]      ; do 16-bits at a time
 | 
						|
        adc     [bx+di],ax
 | 
						|
endif
 | 
						|
        inc     bx
 | 
						|
        inc     bx
 | 
						|
        loop    addlp
 | 
						|
 | 
						|
;  stop as soon as we get an overflow
 | 
						|
        rcl     dx,1            ; save possible overflow
 | 
						|
        or      dx,0000h        ; see if bits left over
 | 
						|
        jz      finshft         ; no possible overflow or increase
 | 
						|
        inc     wGMTemp1
 | 
						|
if      _LDATA
 | 
						|
        add     es:[bx+di],dx
 | 
						|
else
 | 
						|
        add     [bx+di],dx
 | 
						|
endif
 | 
						|
        jno     finshft         ; if sign-bit or carry didn't set: continue
 | 
						|
        xor     dx,dx
 | 
						|
        inc     dx
 | 
						|
if      _LDATA
 | 
						|
        mov     es:[bx+di+2],dx
 | 
						|
else
 | 
						|
        mov     [bx+di+2],dx
 | 
						|
endif
 | 
						|
        inc     wGMTemp1        ; increase number of digits in dst
 | 
						|
 | 
						|
finshft:
 | 
						|
        xor     bx,bx
 | 
						|
        mov     dx,bx
 | 
						|
        mov     cx,wGMTemp1     ; number of int's to shift
 | 
						|
 | 
						|
if      _LDATA
 | 
						|
        lds     si,parm1_
 | 
						|
else
 | 
						|
        mov     si,parm1_
 | 
						|
endif
 | 
						|
shlp3:
 | 
						|
        rcl     Word Ptr [bx+si],1      ;  multiply by 2= times 10
 | 
						|
        inc     bx
 | 
						|
        inc     bx
 | 
						|
        loop    shlp3
 | 
						|
 | 
						|
;
 | 
						|
;       high-order bit of int 10 can't be set either
 | 
						|
;
 | 
						|
        rcl     dx,1            ; save carry bit
 | 
						|
        or      dx,0000h        ;  was max size number, if dx!=0
 | 
						|
        jz      cout            ; no bits shifted into carry
 | 
						|
ifdef   DSNOTHING
 | 
						|
        push    ds
 | 
						|
        mov     ax,seg wGMTemp1
 | 
						|
        mov     ds,ax
 | 
						|
        inc     wGMTemp1        ;  otherwise, one more int in number
 | 
						|
        cmp     wGMTemp1,5      ; if working with 5-int number
 | 
						|
        pop     ds
 | 
						|
else
 | 
						|
        inc     wGMTemp1        ;  otherwise, one more int in number
 | 
						|
        cmp     wGMTemp1,5      ; if working with 5-int number
 | 
						|
endif
 | 
						|
        jg      overf           ;overflow: too many digits
 | 
						|
 | 
						|
        mov     [bx+si],dx
 | 
						|
 | 
						|
;
 | 
						|
;       If no overflow, see if we have mult'd # times requested
 | 
						|
;
 | 
						|
cout:
 | 
						|
        test    [si+8],8000h    ; see if high-order word set sign
 | 
						|
        jnz     overf
 | 
						|
 | 
						|
        xor     bx,bx           ; clear flags
 | 
						|
        mov     dx,bx
 | 
						|
ifdef   DSNOTHING
 | 
						|
        push    ds              ; save parm1's DS and switch
 | 
						|
        mov     ax,seg wGMTemp1
 | 
						|
        mov     ds,ax           ; to global's DS
 | 
						|
        mov     cx,wGMTemp1
 | 
						|
        pop     ds              ; then back to parm's DS
 | 
						|
else
 | 
						|
        mov     cx,wGMTemp1
 | 
						|
endif
 | 
						|
 | 
						|
if      _LDATA
 | 
						|
        mov     ax, Word Ptr parm3_
 | 
						|
else
 | 
						|
        mov     ax, Word Ptr parm2_     ; get addend
 | 
						|
endif
 | 
						|
aloop:
 | 
						|
        adc     [bx+si],ax
 | 
						|
        mov     ax,dx
 | 
						|
        inc     bx
 | 
						|
        inc     bx
 | 
						|
        loop    aloop
 | 
						|
 | 
						|
        rcl     dx,1            ; save carry bit
 | 
						|
        or      dx,0000h        ;  was max size number, if dx!=0
 | 
						|
        jz      nout            ; no bits shifted into carry
 | 
						|
ifdef   DSNOTHING
 | 
						|
        push    ds              ; save parm1's DS and switch
 | 
						|
        mov     ax, seg wGMTemp1
 | 
						|
        mov     ds,ax           ; to global's DS
 | 
						|
        inc     wGMTemp1                ;  otherwise, one more int in number
 | 
						|
        cmp     wGMTemp1,5      ; if working with 5-int number
 | 
						|
        pop     ds
 | 
						|
else
 | 
						|
        inc     wGMTemp1        ;  otherwise, one more int in number
 | 
						|
        cmp     wGMTemp1,5      ; if working with 5-int number
 | 
						|
endif
 | 
						|
        jg      overf           ;overflow: too many digits
 | 
						|
 | 
						|
        mov     [bx+si],dx
 | 
						|
 | 
						|
;
 | 
						|
;       If no overflow, see if we have mult'd # times requested
 | 
						|
;
 | 
						|
nout:
 | 
						|
        test    [si+8],8000h    ; see if high-order word set sign
 | 
						|
        jnz     overf
 | 
						|
gexit:
 | 
						|
        mov     ax,GM_SUCCESS
 | 
						|
exit:
 | 
						|
if      _LDATA
 | 
						|
        pop     es
 | 
						|
        pop     ds
 | 
						|
endif
 | 
						|
        cproce
 | 
						|
overf:
 | 
						|
        mov     ax,GM_OVERFLOW  ; here only on overflow
 | 
						|
        jmp short exit
 | 
						|
;
 | 
						|
;       if the msd > 0ccch, or if = 0ccch and the high-order hex
 | 
						|
;  digit of msd -1 > hex c then overflow will occur, otherwise
 | 
						|
;  it won't
 | 
						|
;
 | 
						|
tstover:
 | 
						|
        cmp     ax,0ccch        ; overflow if sign sets during the
 | 
						|
        jg      overf
 | 
						|
        jmp     ct              ; no overflow possible
 | 
						|
        endps
 | 
						|
        END
 |