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

📄 fp.asm

📁 汇编编程艺术
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		dw	-256
;
		dw	0e4a1h, 64bch, 467ch, 0ddd0h, 7e55h	; 1e-128
		db	0
		dw	-128
;
		dw	0e9a5h, 0a539h, 0ea27h, 0a87fh, 7f2ah	; 1e-64
		db	0
		dw	-64
;
		dw	94bah, 4539h, 1eadh, 0cfb1h, 7f94h	; 1e-32
		db	0
		dw	-32
;
		dw	0e15bh, 0c44dh, 94beh, 0e695h, 7fc9h	; 1e-16
		db	0
		dw	-16
;
		dw	0cefdh, 8461h, 7711h, 0abcch, 7fe4h	; 1e-8
		db	0
		dw	-8
;
		dw	652ch, 0e219h, 1758h, 0d1b7h, 7ff1h	; 1e-4
		db	0
		dw	-4
;
		dw	0d70ah, 70a3h, 0a3dh, 0a3d7h, 7ff8h	; 1e-2
		db	0
		dw	-2
;
Div10Value	dw	0cccdh, 0cccch, 0cccch, 0cccch, 7ffbh	; 1e-1
		db	0
		dw	-1
;
		dw	0, 0, 0, 8000h, 7fffh			; 1e0
		db	0
		dw	0
;
;
; PotTblP- Power of ten table.  Holds powers of ten raised to positive
;	   powers of two;
;
;		i.e., x(12-n) = 10 ** (2 ** n) for 0 <= n <= 12.
;		      x(13) = 1.0
;		      x(-1) = 10 ** (2 ** -4096)
;
; There is a -1 entry since it is possible for the algorithm to back up
; before the table.
;
		dw	979bh, 8a20h, 5202h, 0c460h, 0b525h	; 1e+4096
		db	0
		dw	4096
;
PotTblP		dw	979bh, 8a20h, 5202h, 0c460h, 0b525h	; 1e+4096
		db	0
		dw	4096
;
		dw	5de5h, 0c53dh, 3b5dh, 9e8bh, 09a92h	; 1e+2048
		db	0
		dw	2048
;
		dw	0c17h, 8175h, 7586h, 0c976h, 08d48h	; 1e+1024
		db	0
		dw	1024
;
		dw	91c7h, 0a60eh, 0a0aeh, 0e319h, 086a3h	; 1e+512
		db	0
		dw	512
;
		dw	0de8eh, 9df9h, 0ebfbh, 0aa7eh, 08351h	; 1e+256
		db	0
		dw	256
;
		dw	8ce0h, 80e9h, 47c9h, 93bah, 081a8h	; 1e+128
		db	0
		dw	128
;
		dw	0a6d5h, 0ffcfh, 1f49h, 0c278h, 080d3h	; 1e+64
		db	0
		dw	64
;
		dw	0b59eh, 2b70h, 0ada8h, 9dc5h, 08069h	; 1e+32
		db	0
		dw	32
;
		dw	0, 400h, 0c9bfh, 8e1bh, 08034h		; 1e+16
		db	0
		dw	16
;
		dw	0, 0, 2000h, 0bebch, 08019h		; 1e+8
		db	0
		dw	8
;
		dw	0, 0, 0, 9c40h, 0800ch			; 1e+4
		db	0
		dw	4
;
		dw	0, 0, 0, 0c800h, 08005h			; 1e+2
		db	0
		dw	2
;
		dw	0, 0, 0, 0a000h, 08002h			; 1e+1
		db	0
		dw	1
;
		dw	0, 0, 0, 8000h, 7fffh			; 1e0
		db	0
		dw	0
;
;
;
;
;
;
;
; SL_FTOA-	Converts extended precision value in FPACC to a decimal
;		string.  AL contains the field width, AH contains the
;		number of positions after the decimal point.  The format
;		of the converted string is:
;
;			sd.e
;
;		where "s" is a single character which is either a space
;		or "=", "e" is some number of digits which is equal to
;		the value passed in AL, and "d" is the number of digits
;		given by  (AL-AH-2).  If the field width is too small,
;		this routine creates a string of "#" characters AH long.
;
;		ES:DI contains the address where we're supposed to put
;		the resulting string.  This code assumes that there is
;		sufficient memory to hold (AL+1) characters at this address.
;
;
;
		public	sl_ftoa
sl_ftoa		proc	far
		push	di
		call	far ptr sl_ftoa2
		pop	di
		ret
sl_ftoa		endp
;
		public	sl_ftoa2
sl_ftoa2	proc	far
		assume	ds:StdGrp
;
		pushf
		push	ds
		push	ax
		push	bx
		push	cx
		push	dx
		push	si
;
		cld
		mov	bx, StdGrp
		mov	ds, bx
;
; Save fpacc 'cause it gets munged.
;
		push	fpacc.Mantissa [0]
		push	fpacc.Mantissa [2]
		push	fpacc.Mantissa [4]
		push	fpacc.Mantissa [6]
		push	fpacc.Exponent
		push	word ptr fpacc.Sign
;
		mov	cx, ax		;Save field width/dec pts here.
;
		call	fpdigits	;Convert fpacc to digit string.
;
; Round the string of digits to the number of significant digits we want to
; display for this number:
;
		mov	bx, DecExponent
		cmp	bx, 18
		jb	PosRS
		xor	bx, bx		;Force to zero if negative or too big.
;
PosRS:		add	bl, ch	       	;Compute position where we should start
		adc	bh, 0		; the rounding.
		inc	bx		;Tweak next digit.
		cmp	bx, 18		;Don't bother rounding if we have
		jae	RoundDone	; more than 18 digits here.
;
; Add 5 to the digit after the last digit we want to print.  Then propogate
; any overflow through the remaining digits.
;
		mov	al, DecDigits [bx]
		add	al, 5
		mov	DecDigits [bx], al
		cmp	al, "9"
		jbe     RoundDone
		sub	DecDigits [bx], 10
RoundLoop:	dec	bx
		js	FirstDigit
		inc	DecDigits[bx]
		cmp	DecDigits[bx], "9"
		jbe	RoundDone
		sub	DecDigits[bx], 10
		jmp	RoundLoop
;
; If we hit the first digit in the string, we've got to shift all the
; characters down one position and put a "1" in the first character
; position.
;
FirstDigit:     mov	bx, DecExponent
		cmp	bx, 18
		jb	FDOkay
		xor	bx, bx
;
FDOkay:		mov	bl, ch
		mov	bh, 0
		inc	bx
FDLp:		mov	al, byte ptr DecDigits[bx-1]
		mov	DecDigits [bx], al
		dec	bx
		jnz	FDLp
		mov	DecDigits, "1"
		inc	DecExponent	;Cause we just added a digit.
;
RoundDone:
;
; See if we're dealing with values greater than one (abs) or between 0 & 1.
;
		cmp	DecExponent, 0	;Handle positive/negative exponents
		jge	PositiveExp	; separately.
;
; Handle values between 0 & 1 here (negative powers of ten).
;
		mov	dl, ch		;Compute #'s width = DecPlaces+3
		add   	dl, 3		;Make room for "-0."
		jc	BadFieldWidth
		cmp	dl, 4
		jae	LengthOk
		mov	dl, 4		;Minimum string is "-0.0"
LengthOK:	mov	al, ' '
PutSpcs2:       cmp	dl, cl
		jae	PS2Done
		stosb
		inc	dl
		jmp	PutSpcs2
;
PS2Done:       	mov	al, DecSign
		stosb
		mov	al, "0"		;Output "0." before the number.
		stosb
		mov	al, "."
		stosb
		mov	ah, 0		;Used to count output digits
		lea	bx, stdGrp:DecDigits ;Pointer to number string.
PutDigits2:	inc	DecExponent
		jns	PutTheDigit
;
; If the exponent value is still negative, output zeros because we've yet
; to reach the beginning of the number.
;
PutZero2:	mov	al, '0'
		stosb
		jmp	TestDone2
;
PutTheDigit:	cmp	ah, 18		;If more than 18 digits so far, just
		jae	PutZero2	; output zeros.
;
		mov	al, [bx]
		inc	bx
		stosb
;
TestDone2:	inc	ah
		dec	ch
		jnz     PutDigits2
		mov	byte ptr es:[di], 0
		jmp	ftoaDone
;
;
; Okay, we've got a positive exponent here.  First, let's adjust the field
; width value (in CH) so that it includes the sign and possible decimal point.
;
PositiveExp:	mov	dx, DecExponent	;Get actual # of digits to left of "."
		inc	dx		;Allow for sign and the fact that there
		inc	dx		; is always one digit to left of ".".
		cmp	ch, 0		;# of chars after "." = 0?
		je	NoDecPt
		add	dl, ch		;Add in number of chars after "."
		adc	dh, 0
		inc	dx		;Make room for "."
NoDecPt:
;
;
; Make sure the field width is bigger than the number of decimal places to
; print.
;
		cmp	cl, ch
		jb	BadFieldWidth
;
;
; Okay, now see if the user is trying to print a value which is too large
; to fit in the given field width:
;
		cmp	dh, 0
		jne	BadFieldWidth	;Sorry, no output >= 256 chars.
		cmp	dl, cl		;Need field width > specified FW?
		jbe	GoodFieldWidth
;
; If we get down here, then we've got a number which will not fit in the
; specified field width.  Fill the string with #'s (sorta like FORTRAN).
;
BadFieldWidth:	mov	ch, 0		;Set CX=field width.
		mov	al, "#"
	rep	stosb
		mov	byte ptr es:[di], 0
		jmp	ftoaDone
;
;
; Print any necessary spaces in front of the number.
;
GoodFieldWidth:	call	PutSpaces
;
; Output the sign character (" " or "-"):
;
		mov	al, DecSign
		stosb
;
; Okay, output the digits for this number here.
;
		mov	ah, 0		;Counts off output characters.
		lea	bx, stdgrp:DecDigits ;Pointer to digit string.
		mov	cl, ch		;CX := # of chars after "."
		mov	ch, 0	       	; plus number of characters before
		add	cx, DecExponent	; the ".".
		inc	cx		;Always at least one digit before "."
OutputLp:	cmp	ah, 18		;Exceeded 18 digits?
		jae	PutZeros
		mov	al, [bx]
		inc	bx
		jmp	PutChar
;
PutZeros:	mov	al, '0'
PutChar:	stosb
		cmp	DecExponent, 0
		jne	DontPutPoint
		mov	al, '.'
		stosb
;
DontPutPoint:	dec	DecExponent
		inc	ah
		loop	OutputLp
		mov	byte ptr es:[di], 0 	;Output the zero byte.
;
ftoaDone:	pop	word ptr fpacc.Sign
		pop	fpacc.Exponent
		pop	fpacc.Mantissa [6]
		pop	fpacc.Mantissa [4]
		pop	fpacc.Mantissa [2]
		pop	fpacc.Mantissa [0]
		pop	si
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	ds
		popf
		ret
sl_ftoa2	endp
;
;
;
;
; Okay, now we need to insert any necessary leading spaces.  We need to
; put (FieldWidth - ActualWidth) spaces before the string of digits.
;
PutSpaces	proc	near
		cmp	dl, cl		;See if print width >= field width
		jae	NoSpaces
		mov	ah, cl
		sub	ah, dl		;Compute # of spaces to print.
		mov	al, ' '
PSLp:		stosb
		dec	ah
		jnz	PSLp
NoSpaces:	ret
PutSpaces	endp
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; SL_ETOA-	Converts value in FPACC to exponential form.  AL contains
;		the number of print positions.  ES:DI points to the array
;		which will hold this string (it must be at least AL+1 chars
;		long).
;
;		The output string takes the format:
;
;		{" "|-} [0-9] "." [0-9]* "E" [+|-] [0-9]{2,4}
;
;		(The term "[0-9]{2,4}" means either two or four digits)
;
;		AL must be at least eight or this code outputs #s.
;
		public	sl_etoa
sl_etoa		proc	far
		push	di
		call	far ptr sl_etoa2
		pop	di
		ret
sl_etoa		endp
;
;
		public	sl_etoa2
sl_etoa2	proc	far
		assume	ds:StdGrp
;
		pushf
		push	ds
		push	ax
		push	bx
		push	cx
		push	si
;
		cld
		mov	bx, StdGrp
		mov	ds, bx
;
		push	fpacc.Mantissa [0]
		push	fpacc.Mantissa [2]
		push	fpacc.Mantissa [4]
		push	fpacc.Mantissa [6]
		push	fpacc.Exponent
		push	word ptr fpacc.Sign
;
		call	fpdigits
;
; See if we have sufficient room for the number-
;
		mov	ah, 0
		mov	cx, ax
;
; Okay, take out spots for sign, ".", "E", sign, and at least four exponent
; digits and the exponent's sign:
;
Subtract2:	sub	ax, 8
		jc	BadEWidth
		jnz	DoTheRound	;Make sure at least 1 digit left!
;
BadEWidth:	mov	ch, 0
		mov	al, "#"
	rep	stosb
		mov	al, 0
		stosb
		jmp	etoaDone
;
; Round the number to the specified number of places.
;
DoTheRound:	mov	ch, al		;# of decimal places is # of posns.
		mov	bl, ch	       	;Compute position where we should start
		mov	bh, 0		; the rounding.
		cmp	bx, 18		;Don't bother rounding if we have
		jae	eRoundDone	; more than 18 digits here.
;
; Add 5 to the digit after the last digit we want to print.  Then propogate
; any overflow through the remaining digits.
;
		mov	al, DecDigits [bx]
		add	al, 5
		mov	DecDigits [bx], al
		cmp	al, "9"
		jbe     eRoundDone
		sub	DecDigits [bx], 10
eRoundLoop:	dec	bx
		js	eFirstDigit
		inc	DecDigits[bx]
		cmp	DecDigits[bx], "9"
		jbe	eRoundDone
		sub	DecDigits[bx], 10
		jmp	eRoundLoop
;
; If we hit the first digit in the string, we've got to shift all the
; characters down one position and put a "1" in the first character
; position.
;
eFirstDigit:    mov	bl, ch
		mov	bh, 0
		inc	bx
eFDLp:		mov	al, byte ptr DecDigits[bx-1]
		mov	DecDigits [bx], al
		dec	bx
		jnz	eFDLp
		mov	DecDigits, "1"
		inc	DecExponent	;Cause we just added a digit.
;
eRoundDone:
;
; Okay, output the value here.
;
		mov	cl, ch		;Set CX=Number of output chars
		mov	ch, 0
		mov	al, DecSign
		stosb
		lea	si, stdgrp:DecDigits
		movsb			;Output first char.
		dec	cx		;See if we're done!
		jz	PutExponent
;
; Output the fractional part here
;
		mov	al, "."
		stosb
		mov	ah, 17		;Max # of chars to output.
PutFractional:	cmp	ah, 0
		jz	NoMoreDigs
		movsb
		dec	ah
		jmp	NextFraction
;
; If we've output more than 18 digits, just output zeros.
;
NoMoreDigs:	mov	al, "0"
		stosb
;
NextFraction:	loop	PutFractional
PutExponent:	mov	al, "E"
		stosb
		mov	al, "+"
		cmp	DecExponent, 0
		jge	NoNegExp
		mov	al, "-"
		neg	DecExponent
;
NoNegExp:	stosb
		mov	ax, DecExponent
		cwd			;Sets DX := 0.
		mov	cx, 1000
		div	cx
		or	al, "0"
		stosb			;Output 1000's digit
		xchg	ax, dx
		cwd
		mov	cx, 100
		div	cx
		or	al, "0"		;Output 100's digit
		stosb
		xchg	ax, dx
		cwd
		mov	cx, 10
		div	cx
		or	al, "0"		;Output 10's digit
		stosb
		xchg	ax, dx
		or	al, "0"		;Output 1's digit
		stosb
		mov	byte ptr es:[di], 0	;Output zero byte.
;
etoaDone:	pop	word ptr fpacc.Sign
		pop	fpacc.Exponent
		pop	fpacc.Mantissa [6]
		pop	fpacc.Mantissa [4]
		pop	fpacc.Mantissa [2]
		pop	fpacc.Mantissa [0]
		pop	si
		pop	cx
		pop	bx
		pop	ax
		pop	ds
		popf
		ret
sl_etoa2	endp
;
;
;
;
;
; FPDigits- Converts the floating point number in FPACC to a string of
;	    digits (in DecDigits), an integer exponent value (DecExp),
;	    and a sign character (DecSign).  The decimal point is assumed
;	    to be between the first and second characters in the string.
;
FPDigits	proc	near
		assume	ds:StdGrp
		push	ds
		push	ax
		push	bx
		push	cx

⌨️ 快捷键说明

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