⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fp.asm

📁 汇编编程艺术
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		or	ax, si
		jnz	FMulDone
;
; If underflow occurs, set the result to zero.
;
		mov	fpacc.exponent, ax
		mov	fpacc.sign, al
;
FMulDone:	pop	di
		pop	si
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	ds
		ret
sl_fmul		endp
		assume	ds:nothing
;
;
;
;
; Mul64- Multiplies the 8 bytes in fpacc.mant by the 8 bytes in fpop.mant
;	 and leaves the result in fprod.
;
Mul64		proc	near
		assume	ds:StdGrp
		xor	ax, ax
		mov	fprod[0], ax
		mov	fprod[2], ax
		mov	fprod[4], ax
		mov	fprod[6], ax
		mov	fprod[8], ax
		mov	fprod[10], ax
		mov	fprod[12], ax
		mov	fprod[14], ax
;
; Computing the following (each character represents 16-bits):
;
;	A B C D
;    x  E F G H
;    -------
;
; Product is computed by:
;
;	A B C D
;    x  E F G H
;    ----------
;            HD
;	    HC0
;          HB00
;	  HA000
;	    GD0
;          GC00
;         GB000
;        GA0000
;          FD00
;	  FC000
;        FB0000
;       FA00000
;         ED000
;        EC0000
;       EB00000
;    + EA000000
;    ----------
;      xxxxxxxx
;
; In the loop below, si indexes through A, B, C, and D above (or E, F, G,
; and H since multiplication is commutative).
;
		mov	si, ax			;Set Index to zero.
flp1:		mov	ax, fpacc.mantissa[si]	;Multiply A, B, C, or D
		mul	fpop.mantissa[0]	; by H.
		add	fprod [si], ax		;Add it into the partial
		adc	fprod+2 [si], dx	; product computed so far.
		jnc	NoCarry0
		inc	fprod+4 [si]
		jnz	NoCarry0
		inc	fprod+6 [si]
		jnz	NoCarry0
		inc	fprod+8 [si]
		jnz	NoCarry0
		inc	fprod+10 [si]
		jnz	NoCarry0
		inc	fprod+12 [si]
		jnz	NoCarry0
		inc	fprod+14 [si]
;
NoCarry0:
		mov	ax, fpacc.mantissa[si]	;Multiply A, B, C, or D
		mul	fpop.mantissa[2]	; (selected by SI) by G
		add	fprod+2 [si], ax	; and add it into the
		adc	fprod+4 [si], dx	; partial product.
		jnc	NoCarry1
		inc	fprod+6 [si]
		jnz	NoCarry1
		inc	fprod+8 [si]
		jnz	NoCarry1
		inc	fprod+10 [si]
		jnz	NoCarry1
		inc	fprod+12 [si]
		jnz	NoCarry1
		inc	fprod [14]
;
NoCarry1:
		mov	ax, fpacc.mantissa [si]	;Multiply A, B, C, or D
		mul	fpop.mantissa [4]	; (SI selects) by F and add
		add	fprod+4 [si], ax	; it into the partial prod.
		adc	fprod+6 [si], dx
		jnc	NoCarry2
		inc	fprod+8 [si]
		jnz	NoCarry2
		inc	fprod+10 [si]
		jnz	NoCarry2
		inc	fprod+12 [si]
		jnz	NoCarry2
		inc	fprod+14 [si]
;
NoCarry2:
		mov	ax, fpacc.mantissa [si]	;Multiply A/B/C/D (selected
		mul	fpop.mantissa [6]	; by SI) by E and add it
		add	fprod+6 [si], ax	; into the partial product.
		adc	fprod+8 [si], dx
		jnc	NoCarry3
		inc	fprod+10 [si]
		jnz	NoCarry3
		inc	fprod+12 [si]
		jnz	NoCarry3
		inc	fprod+14 [si]
;
NoCarry3:
		inc	si			;Select next multiplier
		inc	si			; (B, C, or D above).
		cmp	si, 8			;Repeat for 64 bit x 64 bit
		jnb	QuitMul64		; multiply.
		jmp	flp1
QuitMul64:	ret
		assume	ds:nothing
Mul64		endp
;
;
;
;
;
;
;
;
;---------------------------------------------------------------------------
;		Floating Point Division
;---------------------------------------------------------------------------
;
;
;
;
; Floating point division: Divides fpacc by fpop.
;
		public	sl_fdiv
sl_fdiv		proc	far
		assume	ds:StdGrp
		push	ds
		push	ax
		push	bx
		push	cx
		push	dx
		push	si
		push	di
		push	bp
;
		mov	ax, StdGrp
		mov	ds, ax
;
; See if either operand is zero:
;
		mov	ax, fpacc.mantissa[0]	;No need to check exponent!
		or	ax, fpacc.mantissa[2]
		or	ax, fpacc.mantissa[4]
		or	ax, fpacc.mantissa[6]
		jz	QuoIsZero
;
		mov	ax, fpop.mantissa[0]
		or	ax, fpop.mantissa[2]
		or	ax, fpop.mantissa[4]
		or	ax, fpop.mantissa[6]
		jnz	DenomNotZero
;
; Whoops! Division by zero!  Set to largest possible value (+inf) and leave.
;
DivOvfl:	mov	ax, 0ffffh
		mov	fpacc.exponent, ax
		mov	fpacc.mantissa[0], ax
		mov	fpacc.mantissa[2], ax
		mov	fpacc.mantissa[4], ax
		mov	fpacc.mantissa[6], ax
		mov	al, fpop.sign
		xor	fpacc.sign, al
;
; Note: we could also do an INT 0 (div by zero) or floating point exception
; here, if necessary.
;
		jmp	FDivDone
;
;
; If the numerator is zero, the quotient is zero.  Handle that here.
;
QuoIsZero:	xor	ax, ax			;Need this!
		mov	fpacc.sign, al
		mov	fpacc.exponent, ax
		mov	fpacc.mantissa[0], ax
		mov	fpacc.mantissa[2], ax
		mov	fpacc.mantissa[4], ax
		mov	fpacc.mantissa[6], ax
		jmp	FDivDone
;
;
;
; If both operands are non-zero, compute the quotient down here.
;
DenomNotZero:	mov	al, fpop.sign		;Compute the new sign.
		xor	fpacc.sign, al
;
		mov	ax, fpop.exponent	;Compute new exponent.
		sub	ax, 7fffh		;Subtract BIAS.
		mov	bx, fpacc.exponent
		sub	bx, 7fffh
		sub	bx, ax			;Compute new exponent
		jo	DivOvfl
		add	bx, 7fffh		;Add in BIAS
		mov	fpacc.exponent, bx	;Save as new exponent.
;
; Okay, compute the quotient of the mantissas down here.
;
		call	Div64
;
; Normalize the Quotient.
;
		mov	cx, fpacc.exponent
		jmp	short TestNrmDiv
;
; Normalize by shifting 16 bits at a time here.
;
NrmDiv1:	sub	cx, 16
		mov	ax, fpacc.mantissa[4]
		mov	fpacc.mantissa[6], ax
		mov	ax, fpacc.mantissa[2]
		mov	fpacc.mantissa[4], ax
		mov	ax, fpacc.mantissa[0]
		mov	fpacc.mantissa[2], ax
		mov	fpacc.mantissa[0], 0
TestNrmDiv:     cmp	cx, 16
		jb	DoNrmDiv8
		mov  	ax, fpacc.mantissa[6]
		or	ax, ax
		jz	NrmDiv1
;
; Normalize by shifting eight bits at a time here.
;
; See if we can shift the product a whole byte
;
DoNrmDiv8:	cmp	byte ptr fpacc.mantissa[7], 0
		jnz	DoOneBitsDiv
		cmp	cx, 8
		jb	DoOneBitsDiv
		mov	ax, fpacc.mantissa[5]
		mov	fpacc.mantissa[6], ax
		mov	ax, fpacc.mantissa[3]
		mov	fpacc.mantissa[4], ax
		mov	ax, fpacc.mantissa[1]
		mov	fpacc.mantissa[2], ax
		mov	al, byte ptr fpacc.mantissa[0]
		mov	byte ptr fpacc.mantissa[1], al
		mov	byte ptr fpacc.mantissa[0], 0
		sub	cx, 8
;
DoOneBitsDiv:	mov	ax, fpacc.mantissa[6]
		mov	bx, fpacc.mantissa[4]
		mov	dx, fpacc.mantissa[2]
		mov	si, fpacc.mantissa[0]
		jmp	short TestOneBitsDiv
;
; One bit at a time normalization here.
;
OneBitLoopDiv:	shl	si, 1
		rcl	dx, 1
		rcl	bx, 1
		rcl	ax, 1
		dec	cx
TestOneBitsDiv:	jcxz	StoreQuo
		test	ah, 80h
		jz	OneBitLoopDiv
;
StoreQuo:	mov	fpacc.mantissa[6], ax
		mov	fpacc.mantissa[4], bx
		mov	fpacc.mantissa[2], dx
		mov	fpacc.mantissa[0], si
		mov	fpacc.exponent, cx
		or	ax, bx
		or	ax, dx
		or	ax, si
		jnz	FDivDone
;
; If underflow occurs, set the result to zero.
;
		mov	fpacc.exponent, ax
		mov	fpacc.sign, al
;
FDivDone:	pop	bp
		pop	di
		pop	si
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	ds
		ret
sl_fdiv		endp
		assume	ds:nothing
;
;
;
;
; Div64- Divides the 64-bit fpacc.mantissa by the 64-bit fpop.mantissa.
;
div64		proc	near
		assume	ds:StdGrp
;
;
; First, normalize fpop if necessary and possible:
;
		mov	ax, fpop.mantissa[6]
		mov	bx, fpop.mantissa[4]
		mov	cx, fpop.mantissa[2]
		mov	dx, fpop.mantissa[0]
		mov	si, fpacc.exponent
		jmp	short Div16NrmTest
;
; The following loop normalizes fpop 16 bits at a time.
;
Div16NrmLp:	mov	ax, bx
		mov	bx, dx
		mov	cx, dx
		xor	dx, dx
		add	si, 16
Div16NrmTest:	cmp	si, -16
		ja	Div16Nrm8		;Must be unsigned because this
		or	ax, ax			; is bias arithmetic, not
		jz	Div16NrmLp		; two's complement!
;
;
; The following code checks to see if it can normalize by eight bits at
; a time.
;
Div16Nrm8:	cmp	si, -8
		ja	Div1NrmTest		;Must be unsigned!
		cmp	ah, 0
		jnz	Div1NrmTest
		mov	ah, al
		mov	al, bh
		mov	bh, bl
		mov	bl, ch
		mov	ch, cl
		mov	cl, dh
		mov	dh, dl
		mov	dl, 0
		add	si, 8
		jmp	short Div1NrmTest
;
; Down here we're stuck with the slow task of normalizing by a bit
; at a time.
;
Div1NrmLp:	shl	dx, 1
		rcl	cx, 1
		rcl	bx, 1
		rcl	ax, 1
		inc	si
Div1NrmTest:	cmp	si, -1
		je	DivOvfl2		;Can't do it!
		test	ah, 80h
		jz	Div1NrmLp
		jmp	short DoSlowDiv
;
; If overflow occurs, set FPACC to the maximum possible value and quit.
;
DivOvfl2:	mov	ax, 0ffffh
		mov	fpacc.exponent, ax
		mov	fpacc.mantissa[0], ax
		mov	fpacc.mantissa[2], ax
		mov	fpacc.mantissa[4], ax
		mov	fpacc.mantissa[6], ax
		jmp	QuitDiv
;
; Oh No! A GawdAwful bit-by-bit division routine.  Terribly slow!
; Actually, it was sped up a little by checking to see if it could
; shift eight or sixteen bits at a time (because it encounters eight
; or sixteen zeros during the division).
;
; Could possibly speed this up some more by checking for the special
; case of n/16 bits.  Haven't tried this idea out though.
;
DoSlowDiv:	mov	fpacc.exponent, si
		mov	si, ax
		mov	di, bx
		mov	fpop.mantissa[2], cx
		mov	fpop.mantissa[0], dx
		mov	ax, fpacc.mantissa[6]
		mov	bx, fpacc.mantissa[4]
		mov	cx, fpacc.mantissa[2]
		mov	dx, fpacc.mantissa[0]
		mov	bp, 64
DivideLoop:	cmp	bp, 16
		jb      Test8
		or	ax, ax
		jnz	Test8
;
; Do a shift by 16 bits here:
;
		mov	ax, Quotient[4]
		mov	Quotient[6], ax
		mov	ax, Quotient[2]
		mov	Quotient[4], ax
		mov	ax, Quotient[0]
		mov	Quotient[2], ax
		mov	Quotient[0], 0
		mov	ax, bx
		mov	bx, cx
		mov	cx, dx
		xor	dx, dx
		sub	bp, 16
		jnz	DivideLoop
		jmp	FinishDivide
;
Test8:		cmp	bp, 8
		jb      Do1
		cmp	ah, 0
		jnz	Do1
;
; Do a shift by 8 bits here:
;
		push	ax
		mov	ax, Quotient[5]
		mov	Quotient[6], ax
		mov	ax, Quotient[3]
		mov	Quotient[4], ax
		mov	ax, Quotient[1]
		mov	Quotient[2], ax
		mov	al, byte ptr Quotient [0]
		mov	byte ptr Quotient [1], al
		mov	byte ptr Quotient[0], 0
		pop	ax
		mov	ah, al
		mov	al, bh
		mov	bh, bl
		mov	bl, ch
		mov	ch, cl
		mov	cl, dh
		mov	dh, dl
		mov	dl, 0
		sub	bp, 8
		jz	FinishDivide2
		jmp	DivideLoop
FinishDivide2:	jmp	FinishDivide
;
Do1:		cmp	ax, si
		jb	shift0
		ja	Shift1
		cmp	bx, di
		jb	shift0
		ja	Shift1
		cmp	cx, fpop.mantissa[2]
		jb	shift0
		ja	shift1
		cmp	dx, fpop.mantissa[0]
		jb	shift0
;
; fpacc.mantiss IS greater than fpop.mantissa, shift a one bit into
; the result here:
;
Shift1:		stc
		rcl	Quotient[0], 1
		rcl	Quotient[2], 1
		rcl	Quotient[4], 1
		rcl	Quotient[6], 1
		sub	dx, fpop.mantissa[0]
		sbb	cx, fpop.mantissa[2]
		sbb	bx, di
		sbb	ax, si
		shl	dx, 1
		rcl	cx, 1
		rcl	bx, 1
		rcl	ax, 1			;Never a carry out.
		dec	bp
		jnz	jDivideLoop
		jmp	FinishDivide
;
; If fpacc.mantissa was less than fpop.mantissa, shift a zero bit into
; the quotient.
;
Shift0:		shl	Quotient[0], 1
		rcl	Quotient[2], 1
		rcl	Quotient[4], 1
		rcl	Quotient[6], 1
		shl	dx, 1
		rcl	cx, 1
		rcl	bx, 1
		rcl	ax, 1
		jc	Greater
		dec	bp
		jnz	jDivideLoop
		jmp	FinishDivide
jDivideLoop:	jmp	DivideLoop
;
; If there was a carry out of the shift, we KNOW that fpacc must be
; greater than fpop.  Handle that case down here.
;
Greater:	dec	bp
		jz	FinishDivide
		stc
		rcl	Quotient[0], 1
		rcl	Quotient[2], 1
		rcl	Quotient[4], 1
		rcl	Quotient[6], 1
		sub	dx, fpop.mantissa[0]
		sbb	cx, fpop.mantissa[2]
		sbb	bx, di
		sbb	ax, si
		shl	dx, 1
		rcl	cx, 1
		rcl	bx, 1
		rcl	ax, 1
		jc	Greater
		dec	bp
		jz	FinishDivide
		jmp	DivideLoop
;
; Okay, clean everything up down here:
;
FinishDivide:	mov	ax, Quotient[0]
		mov	fpacc.mantissa[0], ax
		mov	ax, Quotient[2]
		mov	fpacc.mantissa[2], ax
		mov	ax, Quotient[4]
		mov	fpacc.mantissa[4], ax
		mov	ax, Quotient[6]
		mov	fpacc.mantissa[6], ax
;
QuitDiv:	ret
		assume	ds:nothing
div64		endp
;
;
;
;
;
;---------------------------------------------------------------------------
;		Floating Point => TEXT (Output) conversion routines.
;---------------------------------------------------------------------------
;
;
;
;
; Power of ten tables used by the floating point I/O routines.
;
; Format for each entry (13 bytes):
;
; 1st through
; 11th bytes	Internal FP format for this particular number.
;
; 12th &
; 13th bytes:	Decimal exponent for this value.
;
;
; This first table contains the negative powers of ten as follows:
;
;   for n:= 0 to 12 do
;	entry [12-n] := 10 ** (-2 ** n)
;   entry [13] := 1.0
;
PotTbln         dw	9fdeh, 0d2ceh, 4c8h, 0a6ddh, 4ad8h	; 1e-4096
		db	0					; Sign
		dw	-4096					; Dec Exponent
;
		dw	2de4h, 3436h, 534fh, 0ceaeh, 656bh	; 1e-2048
		db	0
		dw	-2048
;
		dw	0c0beh, 0da57h, 82a5h, 0a2a6h, 72b5h	; 1e-1024
		db	0
		dw	-1024
;
		dw	0d21ch, 0db23h, 0ee32h, 9049h, 795ah	; 1e-512
		db	0
		dw	-512
;
		dw	193ah, 637ah, 4325h, 0c031h, 7cach	; 1e-256
		db	0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -