?? fout.asm
字號:
TITLE FOUT - Free-format numeric output
;***
; FOUT - Free-format numeric output
;
; Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
; Floating Point versions of the routines in IFOUT.ASM
;
; This file is dragged in by the label B$FloatCONASC
;
;
;******************************************************************************
INCLUDE switch.inc
INCLUDE rmacros.inc ; Runtime Macro Defintions
USESEG _DATA
USESEG _BSS
USESEG _TEXT
USESEG RT_TEXT
USESEG XIB ; XIB and XIE must bracket XI!
USESEG XI ;initializer segment
USESEG XIE
USESEG INIT_CODE
INCLUDE seg.inc
INCLUDE baslibma.inc
INCLUDE rtps.inc ; constants shared with QBI
INCLUDE idmac.inc
sBegin _DATA
externW B$AC
externW B$DAC
sEnd _DATA
sBegin _BSS
externB b$SIGN ; defined in CONASC.ASM
externB b$VTYP ; defined in GWDATA.ASM
sEnd _BSS
assumes CS,RT_TEXT
sBegin RT_TEXT
externNP B$ASCRND
;***
;B$FloatFOUTBX - Free-format numeric output for non-integers
;
;Purpose:
; Format number for printing, using BASIC's formatting rules.
;
;Entry:
; BX = ptr to Number to be formatted
; [b$VTYP] = VT_R4, VT_R8 or VT_CY
;
;Exit:
; BX = Address of ASCII string, terminated by 00
; AX = Length of string (not including terminating 00)
;
;Uses:
; Per convention.
;
;Exceptions:
; None.
;****
PUBLIC B$FloatFOUTBX
cProc B$FloatFOUTBX,<NEAR>,<ES,SI,DI>
cBegin
PUSH DS
POP ES
MOV AL,[b$VTYP]
AND AX,0FH ;mask I4s to count of bytes to move
MOV SI,BX
MOV DI,OFFSET DGROUP:B$AC ;point to B$AC
CMP AX,4 ;<= 4 byte quantity?
JBE FourByteVar ;brif so
SUB DI,4 ;use DAC instead of AC
FourByteVar:
XCHG AX,CX
SHR CX,1 ;Count of words
REP MOVSW
CALL B$FloatCONASC ;Most of the work's done here
;Number has been converted to ASCII and is sitting at buffer pointed to by DI.
; SI = address of result buffer
; CX = number of significant figures
; DL has the base 10 exponent of the right end of the digit string.
MOV BX,7 ; If SP, use 7 digits, but limit 7 to right
CMP [b$VTYP],VT_R8 ; What type?
JB RNDDIG ; If I2 or R4, use R4 parameters
MOV BX,16 ; For R8 or I4, 16 digits, limit 16 to right
RNDDIG:
MOV AL,BL
CALL B$ASCRND ;Round to AL digits
MOV AX,DX ; [AX] = exponent
PUSH DX ; save it also
CWD ; sign extend
XOR AX,DX ; [AX] = ABS(exponent)
SUB AX,DX ; adjust
POP DX ; [DX] = exponent
CMP AX,BX ;Too many digits to right of decimal point?
JG SCINOT ;If so, use scientific notation
MOV AX,DX
ADD AX,CX ; AL=number of digits to left of dec.pt.
CMP AX,BX ; Too many?
JG SCINOT ;If so, use scientific notation
XCHG AX,CX ;CX has digits needed to left of dec. pt.
XCHG AX,BX ;BX has digits available from buffer
OR CX,CX ;Any to left?
JLE LESS1 ;If not, start with decimal point
LEFTDP:
MOVSB ;Move digits to final buffer
DEC BX ;Limit to available digits
LOOPNZ LEFTDP
MOV AL,"0"
REP STOSB ;Fill in with place-holding zeros if needed
JZ PUTEND ;If out of digits, were done(flags from DEC BX)
PUTDP:
MOV AL,"."
STOSB ;Put in decimal point
MOV AL,"0" ;Used only if we came from LESS1
REP STOSB ;Add leading zeros if a small number
MOV CX,BX ;Number of digits left
REP MOVSB
PUTEND:
MOV BX,OFFSET DGROUP:b$SIGN ;Leave pointer to buffer
MOV AX,DI
SUB AX,BX ;Length of string
MOV BYTE PTR[DI],0 ;Put in terminating zero
cEnd
LESS1:
;Come here if number is less than one and therefore has no digits to
;left of the decimal point.
NEG CX ;Number of place-holding zeros needed
JMP PUTDP ; after the decimal point
SCINOT:
MOVSB ;Move first digit to final buffer
DEC CX ;Account for digit already moved
JZ EXP ;Skip decimal point if only one digit
MOV AL,"."
STOSB
ADD DX,CX ; Correct exponent for decimal point position
REP MOVSB ;All other digits go after decimal point
EXP:
MOV AX,"+E" ;Prepare "E+" if positive exponent
OR DX,DX ; Check exponent sign
JNS POSEXP
NEG DX ; Force exponent positive
MOV AH,"-"
POSEXP:
CMP [b$VTYP],VT_R8 ; Is type double precision?
JNZ SCISNGL
DEC AX ;Convert the "E" to "D"
SCISNGL:
STOSW
MOV AX,DX ; [AX] = exponent
MOV BL,100
DIV BL ; [AL] = hundreds count
OR AL,AL ; See if any
JZ SCISMALL ; jump if not
OR AL,"0" ; turn into hundreds digit
STOSB ; add leading digit
SCISMALL:
XCHG AL,AH ; get remainder here
AAM ;Convert binary to unpacked BCD
XCHG AL,AH
OR AX,"00" ;Add ASCII bias
STOSW
JMP PUTEND
;
; Rewritten and moved here from CONASC.ASM
;
;***
;B$FloatCONASC - Convert number to ASCII
;
;Purpose:
; Convert number to a string of ASCII digits with no leading or
; trailing zeros. Return base 10 exponent and count of digits.
; No integer values will be passed to this routine.
;
;Entry:
; B$AC has SP number OR B$DAC has DP or CY number
;
;Exit:
; CX = number of significant figures (decimal point to right)
; DL = base 10 exponent
; SI = Address of first digit (non-zero unless number is zero)
; [b$SIGN] has sign - blank if positive, "-" if negative
;
;Uses:
; Uses all.
;****
cProc B$FloatCONASC,<NEAR,PUBLIC>
cBegin
MOV SI,OFFSET DGROUP:B$DAC ;address of location to put final R8
CMP b$VTYP,VT_R8 ;Is it an R8
JE CONASC2 ;brif so, we are ready to convert
GOT_R4:
DbAssertRelB b$VTYP,E,VT_R4,RT_TEXT,<Unknown value for b$VTYP in CONASC>
MOV BX,OFFSET DGROUP:B$AC ;point to AC for R4s
fld dword ptr [bx] ;Load the R4
fstp qword ptr [si] ;And store it as an R8
FWAIT ;ensure stored
CONASC2:
Call FAR PTR B$I8_OUTPUTHack ;math coversion from R8 to ascii string
; At this point $i8_output returns the following conditions
; DS:SI - pointer to converted string (first byte is length)
; AX - 1 if number was ok, 0 if indefinite
; BL - sign character: either ' ' or '-'
; DX - base 10 exponent (left of digits)
; CX,BH - smashed
CONASC3:
MOV b$SIGN,BL ;save sign char
LODSB ;AL = length of strings
CBW
CMP AX,1 ;See if single digit
JNZ ModExp ;If not, go modify exponent
CMP BYTE PTR [SI],"0" ;Else see if number is zero
JZ NoModExp ;If so, leave exponent alone
ModExp:
SUB DX,AX ;DX = base 10 exponent (right of digits)
NoModExp:
XCHG AX,CX ;return num digits in CX
cEnd
sEnd RT_TEXT
assumes CS,_TEXT
sBegin _TEXT
externNP $i8_output ;math pack string conversion
;***
;B$I8_OUTPUTHack - Hack to call B$I8_OUTPUT near from _TEXT.
;
;Purpose:
; Hack to call B$I8_OUTPUT near from _TEXT.
; Convert number to a string of ASCII digits.
;
;Entry:
; DS:SI - ptr to 8 byte double precision number.
;
;Exit:
; DS:SI - pointer to converted string (first byte is length)
; AX - 1 if number was ok, 0 if indefinite
; BL - sign character: either ' ' or '-'
; DX - base 10 exponent
; CX,BH - smashed
;
;Uses:
; Uses all but BP,DI.
;****
cProc B$I8_OUTPUTHack,<FAR>,<BP,DI>
cBegin
cCall $i8_output ;math coversion from R8 to ascii string
; At this point $i8_output returns the following conditions
; DS:SI - pointer to converted string (first byte is length)
; AX - 1 if number was ok, 0 if indefinite
; BL - sign character: either ' ' or '-'
; DX - base 10 exponent
; DI,CX,BH - smashed
cEnd
sEnd _TEXT
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -