Category : Assembly Language Source Code
Archive   : BLUEBOOK.ZIP
Filename : FLOATPT.ASM

 
Output of file : FLOATPT.ASM contained in archive : BLUEBOOK.ZIP
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 <<<<<


  3 Responses to “Category : Assembly Language Source Code
Archive   : BLUEBOOK.ZIP
Filename : FLOATPT.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/