; 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