fout.asm
资源名称:DOS系统的源代码.rar [点击查看]
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:7k
源码类别:
操作系统开发
开发平台:
Visual C++
- 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