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

📄 fp.asm

📁 汇编编程艺术
💻 ASM
📖 第 1 页 / 共 5 页
字号:

		mov	ax, fpacc.Mantissa[0]
		or	ax, fpacc.Mantissa[2]
		or	ax, fpacc.Mantissa[4]
		or	ax, fpacc.Mantissa[6]
		jne	FPACCNot0		; the whole thing is zero.

		mov	ax, fpop.exponent	;If FPACC is zero, simply
		mov	fpacc.exponent, ax	; copy FPOP to FPACC.
		mov	ax, fpop.Mantissa[0]
		mov	fpacc.Mantissa[0], ax
		mov	ax, fpop.Mantissa[2]
		mov	fpacc.Mantissa[2], ax
		mov	ax, fpop.Mantissa[4]
		mov	fpacc.Mantissa[4], ax
		mov	ax, fpop.Mantissa[6]
		mov	fpacc.Mantissa[6], ax
		mov	al, fpop.Sign
		mov	fpacc.Sign, al
		jmp	Done

FPACCNot0:
		mov	ax, fpop.Mantissa[0]
		or	ax, fpop.Mantissa[2]
		or	ax, fpop.Mantissa[4]
		or	ax, fpop.Mantissa[6]
		jne	FPOPNot0
		jmp	Done

; Adjust the smaller of the two operands so that the exponents of the two
; objects are the same:

FPOPNot0:
		mov	cx, fpacc.exponent
		sub	cx, fpop.exponent
		js	gotoAdjustFPA
		jnz	AdjustFPOP
		jmp	Adjusted		;Only if exponents are equal.
gotoAdjustFPA:	jmp	AdjustFPACC
;
; Since the difference of the exponents is negative, the magnitude of FPOP
; is smaller than the magnitude of fpacc.  Adjust FPOP here.
;
AdjustFPOP:	cmp	cx, 64			;If greater than 64, forget
		jb	short By16LoopTest	; it.  Sum is equal to FPACC.
		jmp	Done
;
; If the difference is greater than 16 bits, adjust FPOP a word at a time.
; Note that there may be multiple words adjusted in this fashion.
;
By16Loop:	mov	ax, fpop.mantissa[2]
		mov	fpop.mantissa[0], ax
		mov	ax, fpop.mantissa[4]
		mov	fpop.mantissa[2], ax
		mov	ax, fpop.mantissa[6]
		mov	fpop.mantissa[4], ax
		mov	fpop.mantissa[6], 0
		sub	cx, 16
By16LoopTest:	cmp	cx, 16
		jae	By16Loop
;
; After adjusting sixteen bits at a time, see if there are at least eight
; bits.  Note that this can only occur once, for if you could adjust by
; eight bits twice, you could have adjusted by 16 above.
;
		cmp	cx, 8
		jb	NotBy8
		mov	ax, fpop.mantissa[1]
		mov	fpop.mantissa[0], ax
		mov	ax, fpop.mantissa[3]
		mov	fpop.mantissa[2], ax
		mov	ax, fpop.mantissa[5]
		mov	fpop.mantissa[4], ax
		mov	al, byte ptr fpop.mantissa [7]
		mov	byte ptr fpop.mantissa [6], al
		mov	byte ptr fpop.mantissa[7], 0
		sub	cx, 8
;
; Well, now we're down to a bit at a time.
;
NotBy8:		jcxz	AdjFPOPDone
;
; Load the mantissa into registers to save processing time.
;
		mov	ax, fpop.mantissa[6]
		mov	bx, fpop.mantissa[4]
		mov	dx, fpop.mantissa[2]
		mov	si, fpop.mantissa[0]
By1Loop:	shr	ax, 1
		rcr	bx, 1
		rcr	dx, 1
		rcr	si, 1
		loop	By1Loop
		mov	fpop.mantissa[6], ax	;Save result back into
		mov	fpop.mantissa[4], bx	; fpop.
		mov	fpop.mantissa[2], dx
		mov	fpop.mantissa[0], si
AdjFPOPDone:	jmp     Adjusted
;
;
;
; AdjustFPACC- FPACC was smaller than FPOP, so adjust its bits down here.
;	       This code is pretty much identical to the above, the same
;	       comments apply.
;
AdjustFPACC:	neg	cx			;Take ABS(cx)
		cmp	cx, 64			;If greater than 64, forget
		jb	By16LpTest		; it.
		jmp	SetFPACC2Zero
;
By16Lp:		mov	ax, fpacc.mantissa[2]
		mov	fpacc.mantissa[0], ax
		mov	ax, fpacc.mantissa[4]
		mov	fpacc.mantissa[2], ax
		mov	ax, fpacc.mantissa[6]
		mov	fpacc.mantissa[4], ax
		mov	fpacc.mantissa[6], 0
		sub	cx, 16
By16LpTest:	cmp	cx, 16
		jae	By16Lp
;
		cmp	cx, 8
		jb	NotBy8a
		mov	ax, fpacc.mantissa[1]
		mov	fpacc.mantissa[0], ax
		mov	ax, fpacc.mantissa[3]
		mov	fpacc.mantissa[2], ax
		mov	ax, fpacc.mantissa[5]
		mov	fpacc.mantissa[4], ax
		mov	al, byte ptr fpacc.mantissa [7]
		mov	byte ptr fpacc.mantissa [6], al
		mov	byte ptr fpacc.mantissa[7], 0
		sub	cx, 8
;
NotBy8a:	jcxz	Adjusted
		mov	ax, fpacc.mantissa[6]
		mov	bx, fpacc.mantissa[4]
		mov	dx, fpacc.mantissa[2]
		mov	si, fpacc.mantissa[0]
By1Lp:		shr	ax, 1
		rcr	bx, 1
		rcr	dx, 1
		rcr	si, 1
		loop	By1Lp
		mov	fpacc.mantissa[6], ax
		mov	fpacc.mantissa[4], bx
		mov	fpacc.mantissa[2], dx
		mov	fpacc.mantissa[0], si
		mov	ax, fpop.Exponent	;FPACC assumes the same
		mov	fpacc.Exponent, ax	; exponent as FPOP.
AdjFPACCDone:	jmp     Adjusted
;
; If FPACC is so much smaller than FPOP that it is insignificant, set
; it to zero.
;
SetFPACC2Zero:	xor	ax, ax
		mov	fpacc.mantissa[0], ax
		mov	fpacc.mantissa[2], ax
		mov	fpacc.mantissa[4], ax
		mov	fpacc.mantissa[6], ax
		mov	fpacc.exponent, ax
		mov	fpacc.sign, al
;
; Now that the mantissas are aligned, let's add (or subtract) them.
;
Adjusted:	mov	al, fpacc.sign
		xor	al, fpop.sign
		js	SubEm
;
; If the signs are the same, simply add the mantissas together here.
;
		mov	ax, fpop.mantissa[0]
		add	fpacc.mantissa[0], ax
		mov	ax, fpop.mantissa[2]
		adc	fpacc.mantissa[2], ax
		mov	ax, fpop.mantissa[4]
		adc	fpacc.mantissa[4], ax
		mov	ax, fpop.mantissa[6]
		adc	fpacc.mantissa[6], ax
		jnc	Normalize
;
; If there was a carry out of the addition (quite possible since most
; fp values are normalized) then we need to shove the bit back into
; the number.
;
		rcr	fpacc.mantissa[6], 1
		rcr	fpacc.mantissa[4], 1
		rcr	fpacc.mantissa[2], 1
		rcr	fpacc.mantissa[0], 1
		inc	fpacc.exponent
;
; If there was a carry out of the bottom, add it back in (this rounds the
; result).  No need to worry about a carry out of the H.O. bit this time--
; there is no way to add together two numbers to get a carry *and* all
; one bits in the result.  Therefore, rounding at this point will not
; propagate all the way through.
;
		adc	fpacc.Mantissa [0], 0
		jnc	Normalize
		inc	fpacc.Mantissa [2]
		jnz	Normalize
		inc	fpacc.Mantissa [4]
		jnz	Normalize
		inc	fpacc.Mantissa [6]
		jmp	Normalize
;
;
;
; If the signs are different, we've got to deal with four possibilities:
;
; 1) fpacc is negative and its magnitude is greater than fpop's.
;	Result is negative, fpacc.mant := fpacc.mant - fpop.mant.
;
; 2) fpacc is positive and its magnitude is greater than fpop's.
;	Result is positive, fpacc.mant := fpacc.mant - fpop.mant.
;
; 3) fpacc is negative and its magnitude is less than fpop's.
;	Result is positive, fpacc.mant := fpop.mant - fpacc.mant.
;
; 4) fpacc is positive and its magnitude is less than fpop's.
;	Result is negative, fpacc.mant := fpop.mant - fpacc.mant.
;
SubEm:		mov	ax, fpacc.mantissa[0]
		mov	bx, fpacc.mantissa[2]
		mov	dx, fpacc.mantissa[4]
		mov	si, fpacc.mantissa[6]
		sub	ax, fpop.mantissa[0]
		sbb	bx, fpop.mantissa[2]
		sbb	dx, fpop.mantissa[4]
		sbb     si, fpop.mantissa[6]
		jnc	StoreFPACC
;
; Whoops!  FPOP > FPACC, fix that down here.
;
		not	ax
		not	bx
		not	dx
		not	si
		inc 	ax
		jnz	StoreFPACCSign
		inc	bx
		jnz	StoreFPAccSign
		inc	dx
		jnz	StoreFPAccSign
		inc	si
;
StoreFPAccSign:	xor	fpacc.sign, 80h			;Flip sign if case 3/4.
;
StoreFPAcc:	mov	fpacc.mantissa[0], ax
		mov	fpacc.mantissa[2], bx
		mov	fpacc.mantissa[4], dx
		mov	fpacc.mantissa[6], si


; Normalize the result down here.  Start by shifting 16 bits at a time,
; then eight bits, then one bit at a time.

Normalize:	mov	ax, fpacc.Mantissa[0]	;First, see if the result
		or	ax, fpacc.Mantissa[2]	; is zero.  Can't normalize
		or	ax, fpacc.Mantissa[4]	; if this is the case.
		or	ax, fpacc.Mantissa[6]
		jnz	NormLoop
		mov	fpacc.Exponent, ax	;Force everything to zero
		mov	fpacc.Sign, al		; if result is zero.
		jmp	Done

NormLoop:	mov	ax, fpacc.mantissa[6]
		or	ax, ax		      	;See if zero (which means we
		jnz	Try8Bits		; can shift 16 bits).
		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
		sub	fpacc.exponent, 16
		jmp	NormLoop
;
; Okay, see if we can normalize eight bits at a shot.
;
Try8Bits:	mov	al, byte ptr fpacc.mantissa[7]
		cmp	al, 0
		jnz	Try1Bit
		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[3], ax
		mov	al, byte ptr fpacc.mantissa[0]
		mov	byte ptr fpacc.mantissa[1], al
		mov	byte ptr fpacc.mantissa[0], 0
		sub	fpacc.exponent, 8
;
Try1Bit:	mov	ax, fpacc.mantissa[6]
		test	ah, 80h
		jnz	Done
		mov	bx, fpacc.mantissa[4]
		mov	dx, fpacc.mantissa[2]
		mov	si, fpacc.mantissa[0]
OneBitLp:	dec	fpacc.exponent
		shl	si, 1
		rcl	dx, 1
		rcl	bx, 1
		rcl	ax, 1
		or	ax, ax			;See if bit 15 is set.
		jns	OneBitLp
		mov	fpacc.mantissa[6], ax
		mov	fpacc.mantissa[4], bx
		mov	fpacc.mantissa[2], dx
		mov	fpacc.mantissa[0], si
;
Done:
		pop	si
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	ds
		ret
sl_fadd		endp
;
;
;
;
;
;
;
;
;
;
;---------------------------------------------------------------------------
; Floating point comparison.
;---------------------------------------------------------------------------
;
;
; FCMP
; Compares value in FPACC to value in FPOP.
; Returns -1 in AX if FPACC is less than FPOP,
; Returns 0  in AX if FPACC is equal to FPOP,
; Returns 1  in AX if FPACC is greater than FPOP.
;
; Also returns this status in the flags (by comparing AX against zero
; before returning) so you can use JE, JNE, JG, JGE, JL, or JLE after this
; routine to test the comparison.
;
		public	sl_fcmp
sl_fcmp		proc	far
		assume	ds:StdGrp
		push	ds
		mov	ax, StdGrp
		mov	ds, ax
;
; First compare the signs of the mantissas.  If they are different, the
; negative one is smaller.
;
		mov	al, byte ptr FPACC+10	;Get sign bit
		xor	al, byte ptr FPOP+10	;See if the signs are different
		jns	SameSign
;
; If the signs are different, then the sign of FPACC determines the result
;
		test	byte ptr FPACC+10, 80h
		jnz	IsLT
		jmp	short IsGT
;
; Down here the signs are the same.  First order of business is to compare
; the exponents.  The one with the larger exponent wins.  If the exponents
; are equal, then we need to compare the mantissas.  If the mantissas are
; the same then the two numbers are equal.  If the mantissas are different
; then the larger one wins.  Note that this discussion is for positive values
; only, if the numbers are negative, then we must reverse the win/loss value
; (win=GT).
;
SameSign:	mov	ax, FPACC.exponent	;One thing cool about bias-
		cmp	ax, FPOP.exponent	; 1023 exponents is that we
		ja	MayBeGT			; can use an unsigned compare
		jb	MayBeLT
;
; If the exponents are equal, we need to start comparing the mantissas.
; This straight line code turns out to be about the fastest way to do it.
;
		mov	ax, word ptr FPACC.mantissa+6
		cmp	ax, word ptr FPOP.mantissa+6
		ja	MayBeGT
		jb	MayBeLT
		mov	ax, word ptr FPACC.mantissa+4
		cmp	ax, word ptr FPOP.mantissa+4
		ja	MayBeGT
		jb	MayBeLT
		mov	ax, word ptr FPACC.mantissa+2
		cmp	ax, word ptr FPOP.mantissa+2
		ja	MayBeGT
		jb	MayBeLT
		mov	ax, word ptr FPACC.mantissa
		cmp	ax, word ptr FPOP.mantissa
		ja	MayBeGT
		je	IsEq			;They're equal at this point.
;
; MayBeLT- Looks like less than so far, but we need to check the sign of the
; numbers, if they are negative then FPACC is really GT FPOP.  Remember, the
; sign is not part of the mantissa!
;
MayBeLT:	test	FPACC.sign, 80h
		js	IsGT
;
IsLT:		mov	ax, -1
		jmp	short cmpRtn
;
; Same story here for MayBeGT
;
MayBeGT:	test	FPACC.sign, 80h
		js	IsLT
;
IsGT:		mov	ax, 1
		jmp	short cmpRtn
;
IsEq:		xor	ax, ax
cmpRtn:		pop	ds
		cmp	ax, 0			;Set the flags as appropriate
		ret
sl_fcmp		endp
		assume	ds:nothing
;
;
;
;
;
;
;
;
;
;
;
;
;
;---------------------------------------------------------------------------
;		Floating Point Multiplication
;---------------------------------------------------------------------------
;
;
;
;
; sl_fmul- Multiplies facc by fop and leaves the result in facc.
;
		public	sl_fmul
sl_fmul		proc	far
		assume	ds:StdGrp
		push	ds
		push	ax
		push	bx
		push	cx
		push	dx
		push	si
		push	di
;
		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	ProdIsZero
;
		mov	ax, fpop.mantissa[0]
		or	ax, fpop.mantissa[2]
		or	ax, fpop.mantissa[4]
		or	ax, fpop.mantissa[6]
		jnz	ProdNotZero
;
ProdIsZero:	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	FMulDone
;
; If both operands are non-zero, compute the true product down here.
;
ProdNotZero:	mov	al, fpop.sign		;Compute the new sign.
		xor	fpacc.sign, al
;
; Eliminate bias in the exponents, add them, and check for 16-bit signed
; overflow.
;
		mov	ax, fpop.exponent	;Compute new exponent.
		sub	ax, 7fffh		;Subtract BIAS and adjust
		mov	bx, fpacc.Exponent
		sub	bx, 7fffh
		add	ax, bx			; for fractional multiply.
		jno	GoodExponent
;
; If the exponent overflowed, set up the overflow value here.
;
		mov	ax, 0ffffh
		mov	fpacc.exponent, ax	;Largest exponent value
		mov	fpacc.mantissa[0], ax	; and largest mantissa, too!
		mov	fpacc.mantissa[2], ax
		mov	fpacc.mantissa[4], ax
		mov	fpacc.mantissa[6], ax
		jmp	FMulDone
;
GoodExponent:	add	ax, 8000h		;Add the bias back in (note
		mov	fpacc.Exponent, ax	; Mul64 below causes shift
;						; to force bias of 7fffh.
; Okay, compute the product of the mantissas down here.
;
		call	Mul64
;
; Normalize the product.  Note: we know the product is non-zero because
; both of the original operands were non-zero.
;
		mov	cx, fpacc.exponent
		jmp	short TestNrmMul
NrmMul1:	sub	cx, 16
		mov	ax, fprod[12]
		mov	fprod[14], ax
		mov	ax, fprod[10]
		mov	fprod[12], ax
		mov	ax, fprod[8]
		mov	fprod[10], ax
		mov	ax, fprod[6]
		mov	fprod[8], ax
		mov	ax, fprod[4]
		mov	fprod[6], ax
		mov	ax, fprod[2]
		mov	fprod[4], ax
		mov	ax, fprod[0]
		mov	fprod[2], ax
		mov	fprod[0], 0
TestNrmMul:     cmp	cx, 16
		jb	DoNrmMul8
		mov  	ax, fprod[14]
		or	ax, ax
		jz	NrmMul1
;
; See if we can shift the product a whole byte
;
DoNrmMul8:	cmp	ah, 0			;Contains fprod[15] from above.
		jnz	DoOneBits
		cmp	cx, 8
		jb	DoOneBits
		mov	ax, fprod[13]
		mov	fprod[14], ax
		mov	ax, fprod[11]
		mov	fprod[12], ax
		mov	ax, fprod[9]
		mov	fprod[10], ax
		mov	ax, fprod[7]
		mov	fprod[8], ax
		mov	ax, fprod[5]
		mov	fprod[6], ax
		mov	ax, fprod[3]
		mov	fprod[4], ax
		mov	ax, fprod[1]
		mov	fprod[2], ax
		mov	al, byte ptr fprod[0]
		mov	byte ptr fprod[1], al
		mov	byte ptr fprod[0], 0
		sub	cx, 8
;
DoOneBits:	mov	ax, fprod[14]
		mov	bx, fprod[12]
		mov	dx, fprod[10]
		mov	si, fprod[8]
		mov	di, fprod[6]
		jmp	short TestOneBits
;
OneBitLoop:	shl	fprod[0], 1
		rcl	fprod[2], 1
		rcl	fprod[4], 1
		rcl	di, 1
		rcl	si, 1
		rcl	dx, 1
		rcl	bx, 1
		rcl	ax, 1
		dec	cx
TestOneBits:	jcxz	StoreProd
		test	ah, 80h
		jz	OneBitLoop
;
StoreProd:	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

⌨️ 快捷键说明

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