home *** CD-ROM | disk | FTP | other *** search
- COMMENT ~
- FLOATPT.ASM -- Floating Point Conversion Procedures
-
- From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
- by Christopher L. Morgan
- Copyright (C) 1984 by The Waite Group, Inc.
-
- Purpose:
-
- Contents:
- ---------
- BIN802DEC -- Convert from 80-bit binary to decimal digits
- DECDOUBLE -- Double a temporary decimal floating point number
- DECHALF -- Halve a temporary decimal floating point number
- DECNORM -- Normalize temporary decimal floating point
- DFP2SFP -- Convert from double to single precision floating point
- FIX -- Convert from floating point to 16-bit integer
- FLOAT -- Convert from 16-bit integer to floating point
- FPIN -- Convert from external to internal floating point
- FPINDIGIT -- Input single decimal digit to floating point
- FPOUT -- Convert from internal to external floating point
- FPTDIV -- Divide temporary floating point by 10
- FPTMUL -- Multiply temporary floating point by 10
- FPTNORM -- Normalize temporary floating point
- SFP2DFP -- Convert from single to double precision floating point
- SFP2TFP -- Convert from single precision to temporary floating point
- SGNDEC16IN -- Convert from ASCII signed decimal to binary
- TDECSHOW -- Display floating point
- TFP2SFP -- Convert from temporary floating point to single precision
- _____________________________________________________________________________
- ~
- CODES SEGMENT
-
- EXTRN STDIN:FAR,STDOUT:FAR
-
- PUBLIC SGNDEC16IN,TFP2SFP,FPINDIGIT,FPTNORM,FPTMUL,FPTDIV,FPIN
- PUBLIC SFP2TFP,TDECSHOW,BIN802DEC,DECNORM,DECHALF,DECDOUBLE,FPOUT
- PUBLIC FIX,FLOAT,SFP2DFP,DFP2SFP,MBINADD,MBINSUB,MBINMUL,MBINDIV
-
- ASSUME CS:CODES,DS:DATAS
-
- ;Equates
- SIBYTE EQU BYTE PTR [SI]
- SIWORD EQU WORD PTR [SI]
- DIBYTE EQU BYTE PTR [DI]
- DIWORD EQU WORD PTR [DI]
-
- SFPBUFFW0 EQU WORD PTR SFPBUFF+0
- SFPBUFFB2 EQU BYTE PTR SFPBUFF+2
- SFPBUFFB3 EQU BYTE PTR SFPBUFF+3
- SFPBUFFW2 EQU WORD PTR SFPBUFF+2
-
- DFPBUFFW0 EQU WORD PTR DFPBUFF+0
- DFPBUFFW2 EQU WORD PTR DFPBUFF+2
- DFPBUFFW4 EQU WORD PTR DFPBUFF+4
- DFPBUFFW6 EQU WORD PTR DFPBUFF+6
-
- FPTEMP1W0 EQU WORD PTR FPTEMP1+0
- FPTEMP1W2 EQU WORD PTR FPTEMP1+2
- FPTEMP1W4 EQU WORD PTR FPTEMP1+4
- FPTEMP1W6 EQU WORD PTR FPTEMP1+6
- FPTEMP1W8 EQU WORD PTR FPTEMP1+8
- FPTEMP1B10 EQU BYTE PTR FPTEMP1+10
- FPTEMP1W11 EQU WORD PTR FPTEMP1+11
-
- FPTEMP2W0 EQU WORD PTR FPTEMP2+0
- FPTEMP2W2 EQU WORD PTR FPTEMP2+2
- FPTEMP2W4 EQU WORD PTR FPTEMP2+4
- FPTEMP2W6 EQU WORD PTR FPTEMP2+6
- FPTEMP2W8 EQU WORD PTR FPTEMP2+8
- FPTEMP2B10 EQU BYTE PTR FPTEMP2+10
- FPTEMP2W11 EQU WORD PTR FPTEMP2+11
-
- ;__________________________ FLOATING POINT ROUTINES __________________________
- ;-----------------------------------------------------------------------------
- ;Convert from 80-bit binary to decimal digits
- BIN802DEC PROC NEAR
- ;
- ;Clear the string
- PUSH DI ;Save destination pointer
- MOV AL,0 ;Zero byte
- MOV CX,25 ; for a count of 25
- BIN802DEC1:
- MOV [DI],AL ;Zero the byte
- INC DI ;Point to next byte
- LOOP BIN802DEC1 ; until done
- POP DI ;Restore destination pointer
- ;
- ;Keep looping
- BIN802DEC2:
- PUSH SI ;Save source pointer
- ;
- ;Divide mantissa by 10
- MOV BX,0 ;Done flag
- MOV CX,5 ;5 words in number
- MOV DX,0 ;Previous remainder
- ADD SI,8 ;Point to high end
- BIN802DEC3:
- PUSH CX ;Save count
- MOV AX,[SI] ;Get 16-bit digit
- MOV CX,10 ;Divisor of 10
- DIV CX ;Divide
- MOV [SI],AX ;Put 16-bit digit back
- OR BX,AX ;Check for zero
- SUB SI,2 ;Point to next 16-bit digit
- POP CX ;Restore count
- LOOP BIN802DEC3
- MOV [DI],DL ;Remainder is decimal digit
- INC DI ;Point to next decimal digit
- POP SI ;Restore source pointer
- CMP BX,0 ;Was the binary zero ?
- JNZ BIN802DEC2 ; if so, loop
- RET ; else return
- BIN802DEC ENDP
- ;-----------------------------------------------------------------------------
- ;Double a temporary decimal floating point number
- DECDOUBLE PROC NEAR
- MOV CX,25 ;For a count of 25
- MOV AH,0 ;Clear previous carry
- DECDOUBLE1:
- MOV AL,[DI] ;Get digit
- SAL AL,1 ;Multiply by 2
- ADD AL,AH ;Add the carry
- AAM ;Adjust for dec multiplication
- MOV [DI],AL ;Put the byte back
- INC DI ;Point to next byte
- LOOP DECDOUBLE1
- RET
- DECDOUBLE ENDP
- ;-----------------------------------------------------------------------------
- ;Halve a temporary decimal floating point number
- DECHALF PROC NEAR
- ;
- ;First shift up one digit
- MOV CX,25 ;For a count of 25
- MOV AL,0 ;Zero previous digit
- DECHALF1:
- XCHG AL,[DI] ;Exchange with current digit
- INC DI ;Point to next digit
- LOOP DECHALF1
- DEC DECEXP ;Decrement decimal digit
- ;
- ;Now divide by 2
- MOV CX,25 ;For a count of 25
- MOV AH,0 ;Clear carry
- DECHALF2:
- PUSH CX ;Save count
- DEC DI ;Point to next digit
- MOV AL,[DI] ;Get the digit
- MOV CL,2 ;Divisor of 2
- AAD ;Adjust for decimal division
- DIV CL ;Divide
- MOV [DI],AL ;Put it back
- POP CX ;Restore count
- LOOP DECHALF2
- RET
- DECHALF ENDP
- ;-----------------------------------------------------------------------------
- ;Normalize a temporary decimal floating point number
- DECNORM PROC NEAR
- ;
- ;Check top + 1 digit
- CMP DIBYTE+22,0 ;Is it already zero ?
- JE DECNORM_XIT ;If so, go
- ;
- ;Round up, starting with bottom digit
- MOV AL,[DI] ;First digit
- ADD AL,AL ;Double it for rounding
- MOV AH,0 ;Prepare carry
- AAA ;Adjust for decimal
- ;
- ;Now shift the rest
- MOV CX,24 ;For a count of 24
- DECNORM1:
- MOV AL,[DI+1] ;Get next digit
- ADD AL,AH ;Add carry
- MOV AH,0 ;Prepare next carry
- AAA ;Adjust for decimal
- MOV [DI],AL ;Put digit in place
- INC DI ;Point to next digit
- LOOP DECNORM1
- INC DECEXP ;Increment decimal exponent
- DECNORM_XIT:
- RET
- DECNORM ENDP
- ;-----------------------------------------------------------------------------
- ;Convert from double to single precision floating point
- DFP2SFP PROC FAR
- PUSH AX ;Save register
- MOV AX,DFPBUFFW4 ;Get word from double precision
- MOV SFPBUFFW0,AX ;Put it in single precision
- MOV AX,DFPBUFFW6 ;Get word from double precision
- MOV SFPBUFFW2,AX ;Put it in single precision
- PUSH AX ;Restore register
- RET
- DFP2SFP ENDP
- ;-----------------------------------------------------------------------------
- ;Convert from internal floating point to internal 16-bit integer (truncate)
- FIX PROC FAR
- ;
- ;The number is in SFPBUFF
- PUSH CX ;Save registers
- PUSH AX
- ;
- ;Get the mantissa
- MOV AX,SFPBUFFW0 ;AX gets low part
- MOV AX,SFPBUFFW2 ;DX gets high part
- AND DX,007FH ;Just the mantissa
- OR DX,0080H ;Restore the MSB
- ;
- ;Get the exponent
- MOV CL,SFPBUFFB3
- MOV CH,0 ;Extend to 16-bit
- SUB CX,88H ;Subtract bias +
- CMP CX,0 ;Check its sign
- JL FIX1 ; if negative
- JG FIX3 ; if positive
- JE FIX4 ; if zero
- ;
- ;Shift right
- FIX1:
- NEG CX ;Absolute value
- FIX2:
- SAR DX,1 ;Shift all bits right
- RCR AX,1 ;Carry on
- LOOP FIX2
- JMP FIX4 ;End of case negative
- ;
- ;Shift left
- FIX3:
- SAL AX,1 ;Shift all bits left
- RCL DX,1 ;Carry on
- LOOP FIX3
- JMP FIX4 ;End of case positive
- ;
- ;Check the sign
- FIX4:
- MOV AL,SFPBUFFB2 ;Get sign
- AND AL,80H ;Just bit 7
- JZ FIX_XIT ;Is it on ?
- NEG DX ;Two's complement if negative
- ;
- FIX_XIT:
- POP AX ;Restore registers
- POP CX
- RET
- FIX ENDP
- ;-----------------------------------------------------------------------------
- ;Convert from 16-bit integer to floating point
- FLOAT PROC FAR
- ;
- ;The number is in DX
- PUSH DX ;Save registers
- PUSH CX
- PUSH AX
- MOV AX,0 ;Extend to 32 bits
- CMP DX,0 ;Check if zero
- JZ FLOAT4
- FLOAT1:
- MOV CX,9800H ;Initialize exponent & sign
- ;
- ;Shift left until normalized
- FLOAT2:
- TEST AX,0080H ;Done yet ?
- JNZ FLOAT3 ;If so, go
- SAL DX,1 ;If not, shift all bits left
- RCL AX,1 ;Carry on
- DEC CH ;Decrement the exponent
- JMP FLOAT2
- ;
- ;Pack it in
- FLOAT3:
- AND AX,007FH ;Just the mantissa
- OR AX,CX ;Exponent and sign
- FLOAT4:
- MOV SFPBUFFW0,DX ;Put lower part into place
- MOV SFPBUFFW2,AX ;Put upper part into place
- ;
- ;Show hex for debugging
- LEA SI,INTERNAL ;Point to message
- CALL STDMSG_OUT ;Send it
- MOV DX,SFPBUFFW2 ;Upper word
- CALL HEX16OUT ;Show it
- CALL STD_SPACE ;Skip space
- POP AX ;Restore registers
- POP CX
- POP DX
- RET
- FLOAT ENDP
- ;-----------------------------------------------------------------------------
- ;Convert from external to internal floating point
- FPIN PROC FAR
- PUSH DI ;Save registers
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH AX
- ;
- ;Clear FPTEMP1 buffer
- LEA DI,FPTEMP1 ;Point to FPTEMP1
- MOV AL,0 ;Digit = 0
- CALL FPINDIGIT ;Store digit
- ;
- ;Clear the decimal flag and the count
- MOV DECFLAG,0 ;Clear flag
- MOV DECEXP,0 ;Clear decimal exponent
- ;
- ;Look for the sign
- CALL STD_IN
- CMP AL,'-' ;Minus ?
- JZ FPIN1 ;Store it
- CMP AL,'+' ;Plus ?
- JZ FPIN2 ;Ignore it
- JMP FPIN3 ;Anything else gets used
- ;
- ;Set sign as negative
- FPIN1:
- MOV FPTEMP1B10,80H ;Put sign in place
- FPIN2:
- CALL STD_IN ;Get next digit
- FPIN3:
- CMP AL,'.' ;Check for a decimal place
- JNE FPIN4 ;If not, continue
- ;
- ;Set decimal flag
- CMP DECFLAG,0 ;Decimal flag already set?
- JNE FPIN5 ;Exit if not the first
- MOV DECFLAG,0FFH ;Set it now
- JMP FPIN2 ;Go back for a digit
- FPIN4:
- SUB AL,30H ;Subtract 30H
- JL FPIN5 ;Too low ?
- CMP AL,9
- JG FPIN5 ;Too high ?
- JMP FPIN6 ;Got a digit
- FPIN5:
- JMP FPIN15 ;End of mantissa
- ;
- ;Load digit as a floating point number
- FPIN6:
- LEA DI,FPTEMP2 ;Point to FPTEMP2
- CALL FPINDIGIT ;Put in the digit
- ;
- ;Multiply result by 10
- LEA DI,FPTEMP1 ;Point to FPTEMP1
- CALL FPTMUL ;Multiply by 10
- ;
- ;Pick one with larger exponent
- MOV CX,FPTEMP1W11 ;Get sign of FPTEMP1
- SUB CX,FPTEMP2W11 ;Subtract sign of FPTEMP2
- JE FPIN11 ;Skip if equal
- JG FPIN9 ;If exponent FPTEMP2 is less
- ;
- ;Exponent of FPTEMP1 is less than exponent of FPTEMP2
- FPIN7:
- NEG CX ;Absolute value of exponent
- ;
- ;Shift the bits
- FPIN8:
- SAR FPTEMP1W8,1 ;Shift all bits right
- RCR FPTEMP1W6,1 ;Carry on
- RCR FPTEMP1W4,1
- RCR FPTEMP1W2,1
- RCR FPTEMP1W0,1
- LOOP FPIN8
- ;
- ;Set the exponent
- FPIN9:
- MOV AX,FPTEMP2W11 ;Get exponent of FPTEMP2
- MOV FPTEMP1W11,AX ;Put in exponent of FPTEMP1
- JMP FPIN11 ;Done with this case
- ;
- ;Exponent of FPTEMP2 is less than exponent of FPTEMP1
- ;
- ;Shift the bits
- FPIN10:
- SAR FPTEMP2W8,1 ;Shift all bits right
- RCR FPTEMP2W6,1 ;Carry on
- RCR FPTEMP2W4,1
- RCR FPTEMP2W2,1
- RCR FPTEMP2W0,1
- LOOP FPIN10
- ;
- ;Set the exponent
- MOV AX,FPTEMP1W11 ;Get exponent of FPTEMP1
- MOV FPTEMP2W11,AX ;Put in exponent of FPTEMP2
- JMP FPIN11 ;Done with this case
- ;
- ;Add the digit to the result
- FPIN11:
- MOV CX,5 ;For a count of 5 words
- LEA DI,FPTEMP1 ;DI points to FPTEMP1
- LEA SI,FPTEMP2 ;SI points to FPTEMP2
- CLC
- FPIN12:
- MOV AX,[SI] ;Get 16-bit digit from FPTEMP1
- INC SI ;Point to next 16-bit digit
- INC SI
- ADC [DI],AX ;Add to 16-bit digit of FPTEMP2
- INC DI ;Point to next 16-bit digit
- INC DI
- LOOP FPIN12
- ;
- ;Normalize
- LEA DI,FPTEMP1 ;Point to FPTEMP1
- CALL FPTNORM ;Renormalize it
- ;
- ;Decrement decimal exponent if dec flag is on
- FPIN13:
- CMP DECFLAG,0 ;Check decimal flag
- JE FPIN14 ;Skip if not set
- DEC DECEXP ;Decrement exponent if set
- FPIN14:
- JMP FPIN2 ;Go back for next digit
- ;
- ;Adjust for the decimal point
- FPIN15:
- ADD AL,30H ;Restore ASCII
- AND AL,5FH ;Upper or lower case
- CMP AL,'E' ;Is it 'E' for exponent ?
- JNE FPIN16
- ;
- ;Get exponent
- CALL SGNDEC16IN ;Get signed decimal exponent
- ADD DECEXP,DX ;Add it to current value
- ;
- ;Check for sign of decimal exponent
- FPIN16:
- MOV CX,DECEXP ;Get decimal exponent
- CMP CX,0 ;Check its sign
- JG FPIN17 ;If positive
- JL FPIN18 ;If negative
- ;
- ;Zero count
- JMP FPIN_XIT ;Done if exponent is zero
- ;
- ;Positive decimal exponent
- FPIN17:
- PUSH CX ;Save count = decimal exponent
- ;
- ;Multiply result by 10
- LEA DI,FPTEMP1 ;Point to FPTEMP1
- CALL FPTMUL ;Multiply by 10
- ;
- ;Normalize
- LEA DI,FPTEMP1 ;Point to FPTEMP1
- CALL FPTNORM ;Renormalize it
- POP CX ;Restore the count
- LOOP FPIN17
- JMP FPIN_XIT ;End of this case
- ;
- ;Negative count
- FPIN18:
- NEG CX ;Absolute value of exponent
- FPIN19:
- PUSH CX ;Save the count = exponent
- ;
- ;Divide mantissa by 10
- LEA DI,FPTEMP1 ;Point to FPTEMP1
- CALL FPTDIV ;Divide by 10
- ;
- ;Normalize
- LEA DI,FPTEMP1 ;Point to FPTEMP1
- CALL FPTNORM ;Renormalize it
- POP CX ;Restore the count
- LOOP FPIN19
- ;
- FPIN_XIT:
- CALL TFP2SFP ;Convert to single precision
- POP AX ;Restore registers
- POP CX
- POP DX
- POP SI
- POP DI
- RET
- FPIN ENDP
- ;-----------------------------------------------------------------------------
- ;Convert an input single decimal digit to floating point
- FPINDIGIT PROC NEAR
- ;
- ;Clear the number first
- PUSH DI ;Save pointer
- PUSH AX ;Save digit
- MOV AL,0 ;Zero byte
- MOV CX,13 ;Do 13 bytes
- FPINDIGIT1:
- MOV [DI],AL ;Clear the byte
- INC DI ;Point to next byte
- LOOP FPINDIGIT1 ;Loop for more
- POP AX ;Restore digit
- POP DI ;Restore pointer
- ;
- ;Move the digit into place
- MOV [DI+9],AL ;Place the digit
- RET
- FPINDIGIT ENDP
- ;-----------------------------------------------------------------------------
- ;Convert from internal to external floating point
- FPOUT PROC FAR
- PUSH DI ;Save registers
- PUSH SI
- PUSH DX
- PUSH BX
- PUSH CX
- PUSH AX
- ;
- ;Check for zero as a special case
- MOV AX,SFPBUFFW0 ;Get low word
- OR AX,SFPBUFFW2 ;Get high word
- JNZ FPOUT1 ;Go on, if not zero
- MOV AL,'0' ;Make a zero
- CALL STD_OUT ;Send it out
- JMP FPOUT_XIT ;And exit
- ;
- ;Convert from single precision to temporary floating point
- FPOUT1:
- CALL SFP2TFP ;Convert to temporary format
- ;
- ;Initialize exponent for un-normalized position
- MOV DECEXP,21 ;Exponent = 21 for start
- ;
- ;Set the sign
- MOV AL,FPTEMP1B10 ;Get sign
- MOV DECSIGN,AL ;Put it away
- ;
- ;Convert mantissa to a decimal string
- LEA SI,FPTEMP1 ;SI points to FPTEMP1
- LEA DI,DECBUFF ;DI points to DECBUFF
- CALL BIN802DEC ;Make decimal string
- ;
- ;Check sign of binary exponent
- MOV CX,FPTEMP1W11 ;Get the binary exponent
- SUB CX,72 ;Biased by -72
- CMP CX,0 ;Check its sign
- JL FPOUT2 ;If negative
- JG FPOUT4 ;If positive
- JMP FPOUT5 ;If zero
- FPOUT3:
- PUSH CX ;Absolute value of exponent
- ;
- ;Divide by 2
- LEA DI,DECBUFF ;Point to DECBUFF
- CALL DECHALF ;Divide by 2
- ;
- ;Normalize
- LEA DECBUFF ;Point to DECBUFF
- CALL DECNORM ;Renormalize
- POP CX ;Restore count
- LOOP FPOUT3
- JMP FPOUT5 ;End of case
- ;
- ;Binary exponent is positive
- FPOUT4:
- PUSH CX ;Save count = binary exponent
- ;
- ;Multiply by 2
- LEA DI,DECBUFF ;Point to DECBUFF
- CALL DECDOUBLE ;Multiply by 2
- ;
- ;Normalize
- LEA DECBUFF ;Point to DECBUFF
- CALL DECNORM ;Renormalize
- POP CX ;Restore count
- LOOP FPOUT4
- JMP FPOUT5 ;End of case
- ;
- ;Output the number
- FPOUT5:
- CALL TDECSHOW ;Display the number
- FPOUT_XIT:
- POP AX ;Restore registers
- POP CX
- POP BX
- POP DX
- POP SI
- POP DI
- RET
- FPOUT ENDP
- ;-----------------------------------------------------------------------------
- ;Divide a temporary floating point by 10
- FPTDIV PROC NEAR
- ;
- ;Shift mantissa by 4 places
- MOV CX,4 ;For a count of 4
- FPTDIV1:
- SAL DIWORD+0,1 ;Shift all digits left
- RCL DIWORD+2,1 ;Carry on
- RCL DIWORD+4,1
- RCL DIWORD+6,1
- RCL DIWORD+8,1
- DEC DIWORD+11
- LOOP FPTDIV1
- ;
- ;Divide mantissa by 10
- MOV CX,5 ;5 words in number
- MOV DX,0 ;Previous remainder
- ADD DI,8 ;Point to end
- FPTDIV2:
- PUSH CX ;Save count
- MOV AX,[DI] ;Get 16-bit digit
- MOV CX,10 ;Divisor of 10
- DIV CX ;Divide
- MOV [DI],AX ;Put 16-bit digit back
- SUB DI,2 ;Next 16-bit digit
- POP CX ;Restore count
- LOOP FPTDIV2
- RET
- FPTDIV ENDP
- ;-----------------------------------------------------------------------------
- ;Multiply a temporary floating point by 10
- FPTMUL PROC NEAR
- MOV CX,5 ;For a count of 5
- MOV DX,0 ;Carry of zero
- FPTMUL1:
- PUSH CX ;Save count
- MOV AX,DX ;Previous carry
- XCHG AX,[DI] ;Switch with 16-bit digit
- MOV DX,10 ;Multiplier of 10
- MUL CX ;Multiply
- ADD [DI],AX ;Add into carry in place
- ADD DI,2 ;Next 16-bit digit
- POP CX ;Restore count
- LOOP FPTMUL1
- RET
- FPTMUL ENDP
- ;-----------------------------------------------------------------------------
- ;Normalize a temporary floating point
- FPTNORM PROC NEAR
- CMP DIWORD+8,100H ;Test if too high
- JL FPTNORM_XIT ;Exit if low enough
- SAR DIWORD+8,1 ;Shift right all bytes
- RCR DIWORD+6,1 ;Carry on
- RCR DIWORD+4,1
- RCR DIWORD+2,1
- RCR DIWORD+0,1
- INC DIWORD+11 ;Increment exponent
- FPTNORM_XIT:
- RET
- FPTNORM ENDP
- ;-----------------------------------------------------------------------------
- ;Routine to convert from single to double precision floating point
- SFP2DFP PROC FAR
- PUSH AX ;Save register
- ;
- ;Clear low part of mantissa
- MOV DFPBUFFW0,0 ;Clear low word
- MOV DFPBUFFW2,0 ;Clear next low word
- ;
- ;Move rest of number
- MOV AX,SFPBUFFW0 ;Get word from single precision
- MOV DFPBUFFW4,AX ;Put in double precision
- MOV AX,SFPBUFFW2 ;Get word from single precision
- MOV DFPBUFFW6,AX ;Put in double precision
- POP AX ;Restore registers
- RET
- SFP2DFP ENDP
- ;-----------------------------------------------------------------------------
- ;Routine to convert from single precision to temporary floating point
- SFP2TFP PROC NEAR
- ;
- ;Clear lower part of mantissa
- MOV FPTEMP1W0,0 ;Clear word
- MOV FPTEMP1W2,0 ;Clear word
- MOV FPTEMP1W4,0 ;Clear word
- ;
- ;Move rest of mantissa
- MOV AX,SFPBUFF20 ;Low 2 bytes
- MOV FPTEMP1W6,AX ;Put in place
- MOV AX,SFPBUFFW2 ;High 7 bits
- AND AX,007FH ;Remove sign
- OR AX,0080H ;Restore MSB
- MOV FPTEMP1W8,AX ;Put in place
- ;
- ;Move sign
- MOV AL,SFPBUFFB2 ;In upper byte
- AND AL,80H ;Just sign bit
- MOV FPTEMP1B10,AL ;Byte 10 of FPTEMP1
- ;
- ;Move exponent
- MOV AL,SFPBUFFB3 ;Byte 3 of SFP
- MOV AH,0 ;Make into a word
- SUB AX,80H ;Remove bias
- MOV FPTEMP1W11,AX ;Its 16-bit 2's complement
- RET
- SFP2TFP ENDP
- ;-----------------------------------------------------------------------------
- ;Routine to convert from ASCII signed decimal to binary
- SGNDEC16IN PROC FAR
- MOV DX,0 ;Initialize DX as 0
- MOV CH,0 ;Sign flag
- CALL STD_IN ;Look for sign
- CMP AL,'-' ;Minus ?
- JZ SGNDEC16IN1 ;Store it
- CMP AL,'+' ;Plus ?
- JZ SGNDEC16IN2 ;Ignore it
- JMP SGNDEC16IN3 ;Anything else gets used
- ;
- ;Set sign as negative
- SGNDEC16IN1:
- MOV CH,0FFH ;0FFH is -1
- ;Normal loop
- SGNDEC16IN2:
- CALL STDIN ;Digit comes in AL
- ;Already have a digit ?
- SGNDEC16IN3:
- SUB AL,30H ;Subtract 30H
- JL SGNDEC16IN4 ;Check if too low
- CMP AL,9
- JG SGNDEC16IN4 ;Check if too high
- CBW ;Convert to word
- PUSH CX ;Save sign
- PUSH AX ; and digit
- MOV AX,DX
- MOV CX,10 ;Multiplier of 10
- MUL CX ;Multiply
- MOV DX,AX ;Result in DX
- POP AX ;Restore digit
- ADD DX,AX ;Add in digit
- POP CX ;Restore count
- JMP SGNDEC16IN2
- ;
- ;Resolve the sign
- SGNDEC16IN4:
- CMP CH,0 ;Is it there ?
- JE SGNDEC16IN_XIT ;If not, skip
- NEG DX ;It was negative
- SGNDEC16IN_XIT:
- RET
- SGNDEC16IN ENDP
- ;-----------------------------------------------------------------------------
- ;Routine to display floating point
- TDECSHOW PROC NEAR
- ;
- ;Output the sign
- CMP DECSIGN,0 ;Is it there ?
- MOV AL,' ' ;Space if not
- JE TDECSHOW1
- ;
- ;Output a minus sign
- MOV AL,'-' ;Minus sign
- TDECSHOW1:
- CALL STD_OUT ;Send it out
- ;
- ;Output the first digit and a decimal point
- TDECSHOW2:
- LEA SI,DECBUFF+21 ;Point to first digit
- MOV AL,[SI] ;Get it
- DEC SI ;Point to next digit
- ADD AL,30H ;Make it ASCII
- CALL STD_OUT ;Send it out
- ;
- ;Output the rest of the decimal string
- MOV CX,7 ;Only 7 more digits
- TDECSHOW3:
- MOV AL,[SI] ;Get digit
- DEC SI ;Point to next digit
- ADD AL,30H ;Make ASCII
- CALL STD_OUT ;Send it out
- LOOP TDECSHOW3
- MOV AL,'E' ;E for exponent
- CALL STD_OUT ;Send it
- ;
- ;Now the exponent
- MOV DX,DECEXP ;Get exponent
- CMP DX,0 ;Check sign
- MOV AL,'+' ;Plus sign
- JGE TDECSHOW_XIT ;If non-negative
- ;
- ;If negative exponent
- NEG DX ;Absolute value of exponent
- MOV AL,'-' ;Minus sign
- TDECSHOW_XIT:
- CALL STD_OUT ;Output sign of exponent
- CALL DEC16OUT ;Output exponent
- RET
- TDECSHOW ENDP
- ;-----------------------------------------------------------------------------
- ;Routine to convert from temporary floating point to single precision
- TFP2SFP PROC NEAR
- ;
- ;Move mantissa
- MOV AX,FPTEMP1W4 ;Below word
- RCL AX,1 ;Carry for round up
- MOV AX,FPTEMP1W6 ;Low word
- ADC AX,0 ;Low word + carry
- MOV SFPBUFFW0,AX ;Put in place
- MOV DX,AX ;Check for zero
- MOV AX,FPTEMP1W8
- OR DX,AX ;Check this part, too
- AND AX,007FH ;Just bottom 7 bits
- MOV SFPBUFFW2,AX ;Put in place
- ;
- ;Move sign bit
- MOV AL,FPTEMP1B10 ;Byte 10 is sign
- AND AL,80H
- OR SFPBUFFB2,AL ;Bit 7 is sign
- ;
- ;Move exponent
- MOV AX,FPTEMP1W11 ;16-bit 2's complement exponent
- CMP AX,-128 ;Too low ?
- JL TFP2SFP2 ;Error message
- CMP AX,127 ;Too high ?
- JG TFP2SFP3 ;Error message
- ADD AX,80H ;Bias
- CMP DX,0 ;Is mantissa 0 ?
- JNE TFP2SFP1
- MOV AL,0 ;Put biased byte back
- ;
- ;Normal return
- ;Show hex for debugging
- LEA SI,INTERNAL ;Point to message
- CALL STDMSG_OUT ;Send message
- MOV DX,SFPBUFFW2 ;Upper word
- CALL HEX16OUT ;Show it
- MOV DX,SFPBUFFW0 ;Lower word
- CALL HEX16OUT ;Show it
- CALL STD_SPACE ;Skip space
- CLC ;Clear carry
- RET
- ;
- ;Underflow error
- TFP2SFP2:
- LEA SI,UNDERFLOW ;Point to message
- JMP TFP2SFP4
- ;
- ;Overflow error
- TFP2SFP3:
- LEA SI,OVERFLOW ;Point to message
- JMP TFP2SFP4
- TFP2SFP_XIT:
- CALL STDMSG_OUT ;Send message
- STC ;Set carry
- RET
- TFP2SFP ENDP
- ;-----------------------------------------------------------------------------
- ;_____________________________________________________________________________
- ;
- CODES ENDS
- ;
- END
- ;_____________________________________________________________________________
- ;>>>>> Physical EOF FLOATPT.ASM <<<<<