home *** CD-ROM | disk | FTP | other *** search
- ; Static Name Aliases
- ;
- TITLE divm
-
- include qhead.asm
- extrn _mulm:proc
- extrn mdnorm:proc
-
- _DATA SEGMENT
- ;extrn SC:word
- B DW 0
- count DW 0
- quot DW NQ+2 DUP (?)
- _square DW NQ+2 DUP (?)
- _ans DW NQ+2 DUP (?)
- _DATA ENDS
-
- _TEXT SEGMENT
-
-
- ; Macro to accumulate twice the partial product
- z2mul MACRO a,b
- ao = 6 + 2*a
- bo = 6 + 2*b
- co = 8 + 2*a + 2*b
- do = 6 + 2*a + 2*b
- eo = 4 + 2*a + 2*b
- mov ax, word ptr [di]+ao
- mul word ptr [si]+bo
- xor cx,cx
- sal ax,1
- rcl dx,1
- rcl cx,1
- add word ptr [bx]+co,ax
- adc word ptr [bx]+do,dx
- adc word ptr [bx]+eo,cx
- ENDM
-
-
-
-
- extrn _shdn1:PROC
- extrn _shup1:PROC
- extrn _normlz:PROC
- ;
- ; Floating point divide
- ; @stack into @stack+1
- ;
- ;
- ; The program makes use of 80286 16-bit unsigned
- ; MUL and DIV instructions.
- ; -Copyright 1988 by Stephen L. Moshier
-
-
- ; zdiv( source, dest )
- ; dest = numerator
- PUBLIC _divm
- _divm PROC NEAR
- push bp
- mov bp,sp
- push si
- push di
- push bx
- push cx
- push es
-
- push ds
- pop es
-
-
-
- mov si, word ptr [bp]+4 ;source, denominator
- mov di,si
- add si,8
-
- ; Test if the low order denominator is zero.
- lodsw
- or ax,ax
- je tiszer
- jmp nzero
-
- tiszer:
- mov cx,OMG-2
- $iszer:
- lodsw
- or ax,ax
- jne nnzero
- loop $iszer
-
- jmp short yzer
-
-
- nnzero:
- jmp nzero
-
-
- yzer:
- ; Denominator only has one word of significant bits.
- ; Do a single precision divide.
-
- xor bx,bx
- mov dx, word ptr [di]+6 ; denominator value
- ; get numerator and shift down 1
- mov si, word ptr [bp]+6 ;numerator
- add si,4
- lea di, quot+4
- mov cx, OMG
- clc
- $gnum:
- lodsw
- rcr ax,1
- stosw
- loop $gnum
-
- mov ax,bx
- rcr ax,1
- stosw
-
- xor ax,ax
- stosw
-
- lea si, quot+6 ; numerator
- lea di,_ans+6
- mov cx,dx ;denominator
-
- lodsw
- mov dx,ax
- lodsw
- div cx
- stosw
-
- REPT OMG-1
- lodsw
- div cx
- stosw
- ENDM
-
- mov di, word ptr [bp]+6 ; answer
- sub word ptr [di]+2,1
- ; This is the exact quotient since the low order denominator is zero.
- jmp divfin
-
-
- nzero:
-
-
- mov si,di ;get denominator pointer
-
- ; clear temp area
- lea di,quot
- mov cx,NQ+2
- xor ax,ax
- rep stosw
-
- mov cx, word ptr [si]+6 ; denominator value
-
- ; divide numerator = 1 by most significant word of denominator
- ; compute quotient 1/B to 2 word precision
- lea di,quot+6 ; significand of quotient
- mov dx,04000H ; 1.0
-
- REPT 2
- xor ax,ax
- div cx
- stosw
- ENDM
-
- ; Calculate double precision quotient using Taylor series
-
- ; clear out temporary storage
- xor ax,ax
- lea di,_square
- mov cx,2*NQ+4
- rep stosw
-
- ; square the quotient
- lea di,quot
- mov si,di
- lea bx,_square
- z2mul 0,1
- zmul 1,1
- zmul 0,0
-
- ; multiply squared quotient by low order denominator
- mov si, word ptr [bp]+4
- lea di,_square
- lea bx,_ans
- ; di si
- zmul 2,1
- zmul 1,1
- zmul 0,1
- ; shift up 2
- sal word ptr [bx]+10,1
- rcl word ptr [bx]+8,1
- rcl word ptr [bx]+6,1
- sal word ptr [bx]+10,1
- rcl word ptr [bx]+8,1
- rcl word ptr [bx]+6,1
-
- ; subtract from quotient
- lea di,quot
- lea si,_ans
- mov ax, word ptr [si]+8
- sub word ptr [di]+8,ax
- mov ax, word ptr [si]+6
- sbb word ptr [di]+6,ax
-
- ; do first Newton-Raphson iteration to four word precision
- prec = 4
- ; mov count,3
- ;newtlup:
-
- ; Loop is done by in-line code with increasing
- ; arithmetic precision each iteration.
-
- ; Start of Newton-Raphson iterations.
- rept NQDIV
-
- ; limit precision to maximum available
- if prec gt OMG-1
- prec = OMG-1
- endif
-
- ; clear out accumulators
- lea di,_square
- mov cx,2*NQ+4
- xor ax,ax
- rep stosw
-
- ; Form the square of the approximate quotient
-
- lea si,quot
- mov di,si
- lea bx,_square
-
-
- hh = prec
-
- rept prec
- g = 0
- h = hh
- rept (hh+1)/2
- if g LE OMG-1
- if h LE OMG-1
- z2mul g,h
- endif
- endif
- g = g+1
- h = h-1
- endm
-
- if g EQ h
- xor cx,cx
- zmul g,g
- endif
-
- hh = hh-1
-
- endm
- xor cx,cx
- zmul 0,0
-
-
- ; multiply the square of the quotient by the denominator
-
- mov si, word ptr [bp]+4 ;source, denominator
- lea di,_square
- lea bx,_ans
-
- hh = prec
-
- rept prec
- g = 0
- h = hh
- rept (hh+1)/2
- if g LE OMG-1
- if h LE OMG-2
- zmul g,h
- endif
- endif
- if h LE OMG-1
- if g LE OMG-2
- zmul h,g
- endif
- endif
- g = g+1
- h = h-1
- endm
-
- if g EQ h
- zmul g,g
- endif
-
- hh = hh-1
-
- endm
- zmul 0,0
-
-
- ; shift the product up 1 bit
-
- lea bx,_ans
-
- h = 2*prec+8
- sal word ptr [bx]+h,1
-
- rept prec+2
- h = h-2
- rcl word ptr [bx]+h,1
- endm
-
- ; subtract quot - ans
-
- i = 2*prec+8
- std
- lea si,_ans+i
- lea di,quot
-
- lodsw
- sub word ptr [di]+i,ax
-
- rept prec+2
- i=i-2
- lodsw
- sbb word ptr [di]+i,ax
- endm
- cld
-
- ; shift result up 1 bit
-
- lea bx,quot
-
- h = 2*prec+8
- sal word ptr [bx]+h,1
-
- rept prec+2
- h = h-2
- rcl word ptr [bx]+h,1
- endm
-
- ; increase the arithmetic precision for next loop
- prec = prec+prec
-
- ; end of Newton-Raphson iteration loop
- endm
-
- ; sub count,1
- ; je divdon
- ; jmp newtlup
-
- divdon:
- cld
-
- ; multiply 1/x by the numerator
-
- ; temp area for the product
- lea bx, _ans
- ; clear the temp area
- xor ax,ax
- mov di,bx
- mov cx,NQ+2
- rep stosw
-
- lea si,quot
- ; mov si,WORD PTR [bp+4] ;source
- mov di,WORD PTR [bp+6] ;dest
-
- xor cx,cx ; for adc 0
-
- hh = OMG-1
-
- rept OMG-1
-
- g = 0
- h = hh
- rept (hh+1)/2
- if g LE OMG-2
- if h LE OMG-1
- zmul g,h
- endif
- endif
- if h LE OMG-2
- if g LE OMG-1
- zmul h,g
- endif
- endif
- g = g+1
- h = h-1
- endm
-
- if g EQ h
- zmul g,g
- endif
-
- hh = hh-1
-
- endm
-
- zmul 0,0
-
-
-
- divfin:
-
-
- ; normalize
- mov di, word ptr [bp]+6
- lea bx, _ans
- call mdnorm
-
- ; move out the answer
- lea si, _ans+4
- add di,4
- mov cx,OMG
- rep movsw
-
- pop es
- pop cx
- pop bx
- pop di
- pop si
- pop bp
- ret
- _divm ENDP
-
-
- _TEXT ENDS
- END
-