home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / bluebook.zip / FLOATPT.ASM < prev    next >
Assembly Source File  |  1986-05-14  |  23KB  |  843 lines

  1.                                       COMMENT ~
  2. FLOATPT.ASM -- Floating Point Conversion Procedures
  3.  
  4.    From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
  5.          by Christopher L. Morgan
  6.          Copyright (C) 1984 by The Waite Group, Inc.
  7.  
  8.    Purpose:
  9.  
  10.    Contents:
  11.    ---------
  12.    BIN802DEC    --  Convert from 80-bit binary to decimal digits
  13.    DECDOUBLE    --  Double a temporary decimal floating point number
  14.    DECHALF    --  Halve a temporary decimal floating point number
  15.    DECNORM    --  Normalize temporary decimal floating point
  16.    DFP2SFP    --  Convert from double to single precision floating point
  17.    FIX        --  Convert from floating point to 16-bit integer
  18.    FLOAT    --  Convert from 16-bit integer to floating point
  19.    FPIN        --  Convert from external to internal floating point
  20.    FPINDIGIT    --  Input single decimal digit to floating point
  21.    FPOUT    --  Convert from internal to external floating point
  22.    FPTDIV    --  Divide temporary floating point by 10
  23.    FPTMUL    --  Multiply temporary floating point by 10
  24.    FPTNORM    --  Normalize temporary floating point
  25.    SFP2DFP    --  Convert from single to double precision floating point
  26.    SFP2TFP    --  Convert from single precision to temporary floating point
  27.    SGNDEC16IN    --  Convert from ASCII signed decimal to binary
  28.    TDECSHOW    --  Display floating point
  29.    TFP2SFP    --  Convert from temporary floating point to single precision
  30.  _____________________________________________________________________________
  31.                                                                               ~
  32. CODES    SEGMENT
  33.  
  34.     EXTRN    STDIN:FAR,STDOUT:FAR
  35.     
  36.     PUBLIC SGNDEC16IN,TFP2SFP,FPINDIGIT,FPTNORM,FPTMUL,FPTDIV,FPIN
  37.     PUBLIC SFP2TFP,TDECSHOW,BIN802DEC,DECNORM,DECHALF,DECDOUBLE,FPOUT
  38.     PUBLIC    FIX,FLOAT,SFP2DFP,DFP2SFP,MBINADD,MBINSUB,MBINMUL,MBINDIV
  39.  
  40. ASSUME CS:CODES,DS:DATAS
  41.  
  42. ;Equates
  43.     SIBYTE    EQU    BYTE PTR [SI]
  44.     SIWORD    EQU    WORD PTR [SI]
  45.     DIBYTE  EQU    BYTE PTR [DI]
  46.     DIWORD    EQU    WORD PTR [DI]
  47.  
  48.     SFPBUFFW0    EQU    WORD PTR SFPBUFF+0
  49.     SFPBUFFB2    EQU    BYTE PTR SFPBUFF+2
  50.     SFPBUFFB3    EQU    BYTE PTR SFPBUFF+3
  51.     SFPBUFFW2    EQU    WORD PTR SFPBUFF+2
  52.  
  53.     DFPBUFFW0    EQU    WORD PTR DFPBUFF+0
  54.     DFPBUFFW2    EQU    WORD PTR DFPBUFF+2
  55.     DFPBUFFW4    EQU    WORD PTR DFPBUFF+4
  56.     DFPBUFFW6    EQU    WORD PTR DFPBUFF+6
  57.  
  58.     FPTEMP1W0    EQU    WORD PTR FPTEMP1+0
  59.     FPTEMP1W2    EQU    WORD PTR FPTEMP1+2
  60.     FPTEMP1W4    EQU    WORD PTR FPTEMP1+4
  61.     FPTEMP1W6    EQU    WORD PTR FPTEMP1+6
  62.     FPTEMP1W8    EQU    WORD PTR FPTEMP1+8
  63.     FPTEMP1B10    EQU    BYTE PTR FPTEMP1+10
  64.     FPTEMP1W11    EQU    WORD PTR FPTEMP1+11
  65.  
  66.     FPTEMP2W0    EQU    WORD PTR FPTEMP2+0
  67.     FPTEMP2W2    EQU    WORD PTR FPTEMP2+2
  68.     FPTEMP2W4    EQU    WORD PTR FPTEMP2+4
  69.     FPTEMP2W6    EQU    WORD PTR FPTEMP2+6
  70.     FPTEMP2W8    EQU    WORD PTR FPTEMP2+8
  71.     FPTEMP2B10    EQU    BYTE PTR FPTEMP2+10
  72.     FPTEMP2W11    EQU    WORD PTR FPTEMP2+11
  73.  
  74. ;__________________________ FLOATING POINT ROUTINES __________________________
  75. ;-----------------------------------------------------------------------------
  76. ;Convert from 80-bit binary to decimal digits
  77. BIN802DEC    PROC    NEAR
  78. ;
  79. ;Clear the string
  80.     PUSH    DI                ;Save destination pointer
  81.     MOV    AL,0                ;Zero byte
  82.     MOV    CX,25                ; for a count of 25
  83. BIN802DEC1:
  84.     MOV    [DI],AL                ;Zero the byte
  85.     INC    DI                ;Point to next byte
  86.     LOOP    BIN802DEC1            ; until done
  87.     POP    DI                ;Restore destination pointer
  88. ;
  89. ;Keep looping
  90. BIN802DEC2:
  91.     PUSH    SI                ;Save source pointer
  92. ;
  93. ;Divide mantissa by 10
  94.     MOV    BX,0                ;Done flag
  95.     MOV    CX,5                ;5 words in number
  96.     MOV    DX,0                ;Previous remainder
  97.     ADD    SI,8                ;Point to high end
  98. BIN802DEC3:
  99.     PUSH    CX                ;Save count
  100.     MOV    AX,[SI]                ;Get 16-bit digit
  101.     MOV    CX,10                ;Divisor of 10
  102.     DIV    CX                ;Divide
  103.     MOV    [SI],AX                ;Put 16-bit digit back
  104.     OR    BX,AX                ;Check for zero
  105.     SUB    SI,2                ;Point to next 16-bit digit
  106.     POP    CX                ;Restore count
  107.     LOOP    BIN802DEC3
  108.     MOV    [DI],DL                ;Remainder is decimal digit
  109.     INC    DI                ;Point to next decimal digit
  110.     POP    SI                ;Restore source pointer
  111.     CMP    BX,0                ;Was the binary zero ?
  112.     JNZ    BIN802DEC2            ; if so, loop
  113.     RET                    ; else return
  114. BIN802DEC    ENDP
  115. ;-----------------------------------------------------------------------------
  116. ;Double a temporary decimal floating point number
  117. DECDOUBLE    PROC    NEAR
  118.     MOV    CX,25                ;For a count of 25
  119.     MOV    AH,0                ;Clear previous carry
  120. DECDOUBLE1:
  121.     MOV    AL,[DI]                ;Get digit
  122.     SAL    AL,1                ;Multiply by 2
  123.     ADD    AL,AH                ;Add the carry
  124.     AAM                    ;Adjust for dec multiplication
  125.     MOV    [DI],AL                ;Put the byte back
  126.     INC    DI                ;Point to next byte
  127.     LOOP    DECDOUBLE1
  128.     RET
  129. DECDOUBLE    ENDP
  130. ;-----------------------------------------------------------------------------
  131. ;Halve a temporary decimal floating point number
  132. DECHALF    PROC    NEAR
  133. ;
  134. ;First shift up one digit
  135.     MOV    CX,25                ;For a count of 25
  136.     MOV    AL,0                ;Zero previous digit
  137. DECHALF1:
  138.     XCHG    AL,[DI]                ;Exchange with current digit
  139.     INC    DI                ;Point to next digit
  140.     LOOP    DECHALF1
  141.     DEC    DECEXP                ;Decrement decimal digit
  142. ;
  143. ;Now divide by 2
  144.     MOV    CX,25                ;For a count of 25
  145.     MOV    AH,0                ;Clear carry
  146. DECHALF2:
  147.     PUSH    CX                ;Save count
  148.     DEC    DI                ;Point to next digit
  149.     MOV    AL,[DI]                ;Get the digit
  150.     MOV    CL,2                ;Divisor of 2
  151.     AAD                    ;Adjust for decimal division
  152.     DIV    CL                ;Divide
  153.     MOV    [DI],AL                ;Put it back
  154.     POP    CX                ;Restore count
  155.     LOOP    DECHALF2
  156.     RET
  157. DECHALF        ENDP
  158. ;-----------------------------------------------------------------------------
  159. ;Normalize a temporary decimal floating point number
  160. DECNORM    PROC    NEAR
  161. ;
  162. ;Check top + 1 digit
  163.     CMP    DIBYTE+22,0            ;Is it already zero ?
  164.     JE    DECNORM_XIT            ;If so, go
  165. ;
  166. ;Round up, starting with bottom digit
  167.     MOV    AL,[DI]                ;First digit
  168.     ADD    AL,AL                ;Double it for rounding
  169.     MOV    AH,0                ;Prepare carry
  170.     AAA                    ;Adjust for decimal
  171. ;
  172. ;Now shift the rest
  173.     MOV    CX,24                ;For a count of 24
  174. DECNORM1:
  175.     MOV    AL,[DI+1]            ;Get next digit
  176.     ADD    AL,AH                ;Add carry
  177.     MOV    AH,0                ;Prepare next carry
  178.     AAA                    ;Adjust for decimal
  179.     MOV    [DI],AL                ;Put digit in place
  180.     INC    DI                ;Point to next digit
  181.     LOOP    DECNORM1
  182.     INC    DECEXP                ;Increment decimal exponent
  183. DECNORM_XIT:
  184.     RET
  185. DECNORM        ENDP
  186. ;-----------------------------------------------------------------------------
  187. ;Convert from double to single precision floating point
  188. DFP2SFP    PROC    FAR
  189.     PUSH    AX                ;Save register
  190.     MOV    AX,DFPBUFFW4            ;Get word from double precision
  191.     MOV    SFPBUFFW0,AX            ;Put it in single precision
  192.     MOV    AX,DFPBUFFW6            ;Get word from double precision
  193.     MOV    SFPBUFFW2,AX            ;Put it in single precision
  194.     PUSH    AX                ;Restore register
  195.     RET
  196. DFP2SFP        ENDP
  197. ;-----------------------------------------------------------------------------
  198. ;Convert from internal floating point to internal 16-bit integer (truncate)
  199. FIX    PROC    FAR
  200. ;
  201. ;The number is in SFPBUFF
  202.     PUSH    CX                ;Save registers
  203.     PUSH    AX
  204. ;
  205. ;Get the mantissa
  206.     MOV    AX,SFPBUFFW0            ;AX gets low part
  207.     MOV    AX,SFPBUFFW2            ;DX gets high part
  208.     AND    DX,007FH            ;Just the mantissa
  209.     OR    DX,0080H            ;Restore the MSB
  210. ;
  211. ;Get the exponent
  212.     MOV    CL,SFPBUFFB3            
  213.     MOV    CH,0                ;Extend to 16-bit
  214.     SUB    CX,88H                ;Subtract bias +
  215.     CMP    CX,0                ;Check its sign
  216.     JL    FIX1                ; if negative
  217.     JG    FIX3                ; if positive
  218.     JE    FIX4                ; if zero
  219. ;
  220. ;Shift right
  221. FIX1:
  222.     NEG    CX                ;Absolute value
  223. FIX2:
  224.     SAR    DX,1                ;Shift all bits right
  225.     RCR    AX,1                ;Carry on
  226.     LOOP    FIX2
  227.     JMP    FIX4                ;End of case negative
  228. ;
  229. ;Shift left
  230. FIX3:
  231.     SAL    AX,1                ;Shift all bits left
  232.     RCL    DX,1                ;Carry on
  233.     LOOP    FIX3
  234.     JMP    FIX4                ;End of case positive
  235. ;
  236. ;Check the sign
  237. FIX4:
  238.     MOV    AL,SFPBUFFB2            ;Get sign
  239.     AND    AL,80H                ;Just bit 7
  240.     JZ    FIX_XIT                ;Is it on ?
  241.     NEG    DX                ;Two's complement if negative
  242. ;
  243. FIX_XIT:
  244.     POP    AX                ;Restore registers
  245.     POP    CX
  246.     RET
  247. FIX        ENDP
  248. ;-----------------------------------------------------------------------------
  249. ;Convert from 16-bit integer to floating point
  250. FLOAT    PROC    FAR
  251. ;
  252. ;The number is in DX
  253.     PUSH    DX                ;Save registers
  254.     PUSH    CX        
  255.     PUSH    AX
  256.     MOV    AX,0                ;Extend to 32 bits
  257.     CMP    DX,0                ;Check if zero
  258.     JZ    FLOAT4
  259. FLOAT1:
  260.     MOV    CX,9800H            ;Initialize exponent & sign
  261. ;
  262. ;Shift left until normalized
  263. FLOAT2:
  264.     TEST    AX,0080H            ;Done yet ?
  265.     JNZ    FLOAT3                ;If so, go
  266.     SAL    DX,1                ;If not, shift all bits left
  267.     RCL    AX,1                ;Carry on
  268.     DEC    CH                ;Decrement the exponent
  269.     JMP    FLOAT2
  270. ;
  271. ;Pack it in
  272. FLOAT3:
  273.     AND    AX,007FH            ;Just the mantissa
  274.     OR    AX,CX                ;Exponent and sign
  275. FLOAT4:
  276.     MOV    SFPBUFFW0,DX            ;Put lower part into place
  277.     MOV    SFPBUFFW2,AX            ;Put upper part into place
  278. ;
  279. ;Show hex for debugging
  280.     LEA    SI,INTERNAL            ;Point to message
  281.     CALL    STDMSG_OUT            ;Send it
  282.     MOV    DX,SFPBUFFW2            ;Upper word
  283.     CALL    HEX16OUT            ;Show it
  284.     CALL    STD_SPACE            ;Skip space
  285.     POP    AX                ;Restore registers
  286.     POP    CX    
  287.     POP    DX
  288.     RET
  289. FLOAT        ENDP
  290. ;-----------------------------------------------------------------------------
  291. ;Convert from external to internal floating point
  292. FPIN    PROC    FAR
  293.     PUSH    DI                ;Save registers
  294.     PUSH    SI    
  295.     PUSH    DX
  296.     PUSH    CX
  297.     PUSH    AX
  298. ;
  299. ;Clear FPTEMP1 buffer
  300.     LEA    DI,FPTEMP1            ;Point to FPTEMP1
  301.     MOV    AL,0                ;Digit = 0
  302.     CALL    FPINDIGIT            ;Store digit
  303. ;
  304. ;Clear the decimal flag and the count
  305.     MOV    DECFLAG,0            ;Clear flag
  306.     MOV    DECEXP,0            ;Clear decimal exponent
  307. ;
  308. ;Look for the sign
  309.     CALL    STD_IN            
  310.     CMP    AL,'-'                ;Minus ?
  311.     JZ    FPIN1                ;Store it
  312.     CMP    AL,'+'                ;Plus ?
  313.     JZ    FPIN2                ;Ignore it
  314.     JMP    FPIN3                ;Anything else gets used
  315. ;
  316. ;Set sign as negative
  317. FPIN1:
  318.     MOV    FPTEMP1B10,80H            ;Put sign in place
  319. FPIN2:
  320.     CALL    STD_IN                ;Get next digit
  321. FPIN3:
  322.     CMP    AL,'.'                ;Check for a decimal place
  323.     JNE    FPIN4                ;If not, continue
  324. ;
  325. ;Set decimal flag
  326.     CMP    DECFLAG,0            ;Decimal flag already set?
  327.     JNE    FPIN5                ;Exit if not the first
  328.     MOV    DECFLAG,0FFH            ;Set it now
  329.     JMP    FPIN2                ;Go back for a digit
  330. FPIN4:
  331.     SUB    AL,30H                ;Subtract 30H
  332.     JL    FPIN5                ;Too low ?
  333.     CMP    AL,9
  334.     JG    FPIN5                ;Too high ?
  335.     JMP    FPIN6                ;Got a digit
  336. FPIN5:
  337.     JMP    FPIN15                ;End of mantissa
  338. ;
  339. ;Load digit as a floating point number
  340. FPIN6:
  341.     LEA    DI,FPTEMP2            ;Point to FPTEMP2
  342.     CALL    FPINDIGIT            ;Put in the digit
  343. ;
  344. ;Multiply result by 10
  345.     LEA    DI,FPTEMP1            ;Point to FPTEMP1
  346.     CALL    FPTMUL                ;Multiply by 10
  347. ;
  348. ;Pick one with larger exponent
  349.     MOV    CX,FPTEMP1W11            ;Get sign of FPTEMP1
  350.     SUB    CX,FPTEMP2W11            ;Subtract sign of FPTEMP2
  351.     JE    FPIN11                ;Skip if equal
  352.     JG    FPIN9                ;If exponent FPTEMP2 is less
  353. ;
  354. ;Exponent of FPTEMP1 is less than exponent of FPTEMP2
  355. FPIN7:
  356.     NEG    CX                ;Absolute value of exponent
  357. ;
  358. ;Shift the bits
  359. FPIN8:
  360.     SAR    FPTEMP1W8,1            ;Shift all bits right
  361.     RCR    FPTEMP1W6,1            ;Carry on
  362.     RCR    FPTEMP1W4,1
  363.     RCR    FPTEMP1W2,1
  364.     RCR    FPTEMP1W0,1
  365.     LOOP    FPIN8
  366. ;
  367. ;Set the exponent
  368. FPIN9:
  369.     MOV    AX,FPTEMP2W11            ;Get exponent of FPTEMP2
  370.     MOV    FPTEMP1W11,AX            ;Put in exponent of FPTEMP1
  371.     JMP    FPIN11                ;Done with this case
  372. ;
  373. ;Exponent of FPTEMP2 is less than exponent of FPTEMP1
  374. ;
  375. ;Shift the bits
  376. FPIN10:
  377.     SAR    FPTEMP2W8,1            ;Shift all bits right
  378.     RCR    FPTEMP2W6,1            ;Carry on
  379.     RCR    FPTEMP2W4,1
  380.     RCR    FPTEMP2W2,1
  381.     RCR    FPTEMP2W0,1
  382.     LOOP    FPIN10
  383. ;
  384. ;Set the exponent
  385.     MOV    AX,FPTEMP1W11            ;Get exponent of FPTEMP1
  386.     MOV    FPTEMP2W11,AX            ;Put in exponent of FPTEMP2
  387.     JMP    FPIN11                ;Done with this case
  388. ;
  389. ;Add the digit to the result
  390. FPIN11:
  391.     MOV    CX,5                ;For a count of 5 words
  392.     LEA    DI,FPTEMP1            ;DI points to FPTEMP1
  393.     LEA    SI,FPTEMP2            ;SI points to FPTEMP2
  394.     CLC
  395. FPIN12:
  396.     MOV    AX,[SI]                ;Get 16-bit digit from FPTEMP1
  397.     INC    SI                ;Point to next 16-bit digit
  398.     INC    SI
  399.     ADC    [DI],AX                ;Add to 16-bit digit of FPTEMP2
  400.     INC    DI                ;Point to next 16-bit digit
  401.     INC    DI
  402.     LOOP    FPIN12
  403. ;
  404. ;Normalize
  405.     LEA    DI,FPTEMP1            ;Point to FPTEMP1
  406.     CALL    FPTNORM                ;Renormalize it
  407. ;
  408. ;Decrement decimal exponent if dec flag is on
  409. FPIN13:
  410.     CMP    DECFLAG,0            ;Check decimal flag
  411.     JE    FPIN14                ;Skip if not set
  412.     DEC    DECEXP                ;Decrement exponent if set
  413. FPIN14:
  414.     JMP    FPIN2                ;Go back for next digit
  415. ;
  416. ;Adjust for the decimal point
  417. FPIN15:
  418.     ADD    AL,30H                ;Restore ASCII
  419.     AND    AL,5FH                ;Upper or lower case
  420.     CMP    AL,'E'                ;Is it 'E' for exponent ?
  421.     JNE    FPIN16
  422. ;
  423. ;Get exponent
  424.     CALL    SGNDEC16IN            ;Get signed decimal exponent
  425.     ADD    DECEXP,DX            ;Add it to current value
  426. ;
  427. ;Check for sign of decimal exponent
  428. FPIN16:
  429.     MOV    CX,DECEXP            ;Get decimal exponent
  430.     CMP    CX,0                ;Check its sign
  431.     JG    FPIN17                ;If positive
  432.     JL    FPIN18                ;If negative
  433. ;
  434. ;Zero count
  435.     JMP    FPIN_XIT            ;Done if exponent is zero
  436. ;
  437. ;Positive decimal exponent
  438. FPIN17:
  439.     PUSH    CX                ;Save count = decimal exponent
  440. ;
  441. ;Multiply result by 10
  442.     LEA    DI,FPTEMP1            ;Point to FPTEMP1
  443.     CALL    FPTMUL                ;Multiply by 10
  444. ;
  445. ;Normalize
  446.     LEA    DI,FPTEMP1            ;Point to FPTEMP1
  447.     CALL    FPTNORM                ;Renormalize it
  448.     POP    CX                ;Restore the count
  449.     LOOP    FPIN17
  450.     JMP    FPIN_XIT            ;End of this case
  451. ;
  452. ;Negative count
  453. FPIN18:
  454.     NEG    CX                ;Absolute value of exponent
  455. FPIN19:
  456.     PUSH    CX                ;Save the count = exponent
  457. ;
  458. ;Divide mantissa by 10
  459.     LEA    DI,FPTEMP1            ;Point to FPTEMP1
  460.     CALL    FPTDIV                ;Divide by 10
  461. ;
  462. ;Normalize
  463.     LEA    DI,FPTEMP1            ;Point to FPTEMP1
  464.     CALL    FPTNORM                ;Renormalize it
  465.     POP    CX                ;Restore the count
  466.     LOOP    FPIN19
  467. ;
  468. FPIN_XIT:
  469.     CALL    TFP2SFP                ;Convert to single precision
  470.     POP    AX                ;Restore registers
  471.     POP    CX        
  472.     POP    DX
  473.     POP    SI
  474.     POP    DI
  475.     RET
  476. FPIN        ENDP
  477. ;-----------------------------------------------------------------------------
  478. ;Convert an input single decimal digit to floating point
  479. FPINDIGIT    PROC    NEAR
  480. ;
  481. ;Clear the number first
  482.     PUSH    DI                ;Save pointer
  483.     PUSH    AX                ;Save digit
  484.     MOV    AL,0                ;Zero byte
  485.     MOV    CX,13                ;Do 13 bytes
  486. FPINDIGIT1:
  487.     MOV    [DI],AL                ;Clear the byte
  488.     INC    DI                ;Point to next byte
  489.     LOOP    FPINDIGIT1            ;Loop for more
  490.     POP    AX                ;Restore digit
  491.     POP    DI                ;Restore pointer
  492. ;
  493. ;Move the digit into place
  494.     MOV    [DI+9],AL            ;Place the digit
  495.     RET
  496. FPINDIGIT    ENDP
  497. ;-----------------------------------------------------------------------------
  498. ;Convert from internal to external floating point
  499. FPOUT    PROC    FAR
  500.     PUSH    DI                ;Save registers
  501.     PUSH    SI
  502.     PUSH    DX
  503.     PUSH    BX
  504.     PUSH    CX
  505.     PUSH    AX
  506. ;
  507. ;Check for zero as a special case
  508.     MOV    AX,SFPBUFFW0            ;Get low word
  509.     OR    AX,SFPBUFFW2            ;Get high word
  510.     JNZ    FPOUT1                ;Go on, if not zero
  511.     MOV    AL,'0'                ;Make a zero
  512.     CALL    STD_OUT                ;Send it out
  513.     JMP    FPOUT_XIT            ;And exit
  514. ;
  515. ;Convert from single precision to temporary floating point
  516. FPOUT1:
  517.     CALL    SFP2TFP                ;Convert to temporary format
  518. ;
  519. ;Initialize exponent for un-normalized position
  520.     MOV    DECEXP,21            ;Exponent = 21 for start
  521. ;
  522. ;Set the sign
  523.     MOV    AL,FPTEMP1B10            ;Get sign
  524.     MOV    DECSIGN,AL            ;Put it away
  525. ;    
  526. ;Convert mantissa to a decimal string
  527.     LEA    SI,FPTEMP1            ;SI points to FPTEMP1
  528.     LEA    DI,DECBUFF            ;DI points to DECBUFF
  529.     CALL    BIN802DEC            ;Make decimal string
  530. ;
  531. ;Check sign of binary exponent
  532.     MOV    CX,FPTEMP1W11            ;Get the binary exponent
  533.     SUB    CX,72                ;Biased by -72
  534.     CMP    CX,0                ;Check its sign
  535.     JL    FPOUT2                ;If negative
  536.     JG    FPOUT4                ;If positive
  537.     JMP    FPOUT5                ;If zero
  538. FPOUT3:
  539.     PUSH    CX                ;Absolute value of exponent
  540. ;
  541. ;Divide by 2
  542.     LEA    DI,DECBUFF            ;Point to DECBUFF
  543.     CALL    DECHALF                ;Divide by 2
  544. ;
  545. ;Normalize
  546.     LEA    DECBUFF                ;Point to DECBUFF
  547.     CALL    DECNORM                ;Renormalize
  548.     POP    CX                ;Restore count
  549.     LOOP    FPOUT3
  550.     JMP    FPOUT5                ;End of case
  551. ;
  552. ;Binary exponent is positive
  553. FPOUT4:
  554.     PUSH    CX                ;Save count = binary exponent
  555. ;
  556. ;Multiply by 2
  557.     LEA    DI,DECBUFF            ;Point to DECBUFF
  558.     CALL    DECDOUBLE            ;Multiply by 2
  559. ;
  560. ;Normalize
  561.     LEA    DECBUFF                ;Point to DECBUFF
  562.     CALL    DECNORM                ;Renormalize
  563.     POP    CX                ;Restore count
  564.     LOOP    FPOUT4
  565.     JMP    FPOUT5                ;End of case
  566. ;
  567. ;Output the number
  568. FPOUT5:
  569.     CALL    TDECSHOW            ;Display the number
  570. FPOUT_XIT:
  571.     POP    AX                ;Restore registers
  572.     POP    CX
  573.     POP    BX
  574.     POP    DX
  575.     POP    SI
  576.     POP    DI
  577.     RET    
  578. FPOUT        ENDP
  579. ;-----------------------------------------------------------------------------
  580. ;Divide a temporary floating point by 10
  581. FPTDIV    PROC    NEAR
  582. ;
  583. ;Shift mantissa by 4 places
  584.     MOV    CX,4                ;For a count of 4
  585. FPTDIV1:
  586.     SAL    DIWORD+0,1            ;Shift all digits left
  587.     RCL    DIWORD+2,1            ;Carry on
  588.     RCL    DIWORD+4,1
  589.     RCL    DIWORD+6,1
  590.     RCL    DIWORD+8,1
  591.     DEC    DIWORD+11
  592.     LOOP    FPTDIV1
  593. ;
  594. ;Divide mantissa by 10
  595.     MOV    CX,5                ;5 words in number
  596.     MOV    DX,0                ;Previous remainder
  597.     ADD    DI,8                ;Point to end
  598. FPTDIV2:
  599.     PUSH    CX                ;Save count
  600.     MOV    AX,[DI]                ;Get 16-bit digit
  601.     MOV    CX,10                ;Divisor of 10
  602.     DIV    CX                ;Divide
  603.     MOV    [DI],AX                ;Put 16-bit digit back
  604.     SUB    DI,2                ;Next 16-bit digit
  605.     POP    CX                ;Restore count
  606.     LOOP    FPTDIV2
  607.     RET
  608. FPTDIV        ENDP
  609. ;-----------------------------------------------------------------------------
  610. ;Multiply a temporary floating point by 10
  611. FPTMUL    PROC    NEAR
  612.     MOV    CX,5                ;For a count of 5
  613.     MOV    DX,0                ;Carry of zero
  614. FPTMUL1:
  615.     PUSH    CX                ;Save count
  616.     MOV    AX,DX                ;Previous carry
  617.     XCHG    AX,[DI]                ;Switch with 16-bit digit
  618.     MOV    DX,10                ;Multiplier of 10
  619.     MUL    CX                ;Multiply
  620.     ADD    [DI],AX                ;Add into carry in place
  621.     ADD    DI,2                ;Next 16-bit digit
  622.     POP    CX                ;Restore count
  623.     LOOP    FPTMUL1
  624.     RET
  625. FPTMUL        ENDP
  626. ;-----------------------------------------------------------------------------
  627. ;Normalize a temporary floating point
  628. FPTNORM    PROC    NEAR
  629.     CMP    DIWORD+8,100H            ;Test if too high
  630.     JL    FPTNORM_XIT            ;Exit if low enough
  631.     SAR    DIWORD+8,1            ;Shift right all bytes
  632.     RCR    DIWORD+6,1            ;Carry on
  633.     RCR    DIWORD+4,1            
  634.     RCR    DIWORD+2,1            
  635.     RCR    DIWORD+0,1            
  636.     INC    DIWORD+11            ;Increment exponent
  637. FPTNORM_XIT:
  638.     RET
  639. FPTNORM        ENDP
  640. ;-----------------------------------------------------------------------------
  641. ;Routine to convert from single to double precision floating point
  642. SFP2DFP        PROC    FAR
  643.     PUSH    AX                ;Save register
  644. ;
  645. ;Clear low part of mantissa
  646.     MOV    DFPBUFFW0,0            ;Clear low word
  647.     MOV    DFPBUFFW2,0            ;Clear next low word
  648. ;
  649. ;Move rest of number
  650.     MOV    AX,SFPBUFFW0            ;Get word from single precision
  651.     MOV    DFPBUFFW4,AX            ;Put in double precision
  652.     MOV    AX,SFPBUFFW2            ;Get word from single precision
  653.     MOV    DFPBUFFW6,AX            ;Put in double precision
  654.     POP    AX                ;Restore registers
  655.     RET
  656. SFP2DFP        ENDP
  657. ;-----------------------------------------------------------------------------
  658. ;Routine to convert from single precision to temporary floating point
  659. SFP2TFP    PROC    NEAR
  660. ;
  661. ;Clear lower part of mantissa
  662.     MOV    FPTEMP1W0,0            ;Clear word
  663.     MOV    FPTEMP1W2,0            ;Clear word
  664.     MOV    FPTEMP1W4,0            ;Clear word
  665. ;
  666. ;Move rest of mantissa
  667.     MOV    AX,SFPBUFF20            ;Low 2 bytes
  668.     MOV    FPTEMP1W6,AX            ;Put in place
  669.     MOV    AX,SFPBUFFW2            ;High 7 bits
  670.     AND    AX,007FH            ;Remove sign
  671.     OR    AX,0080H            ;Restore MSB
  672.     MOV    FPTEMP1W8,AX            ;Put in place
  673. ;
  674. ;Move sign
  675.     MOV    AL,SFPBUFFB2            ;In upper byte
  676.     AND    AL,80H                ;Just sign bit
  677.     MOV    FPTEMP1B10,AL            ;Byte 10 of FPTEMP1
  678. ;
  679. ;Move exponent
  680.     MOV    AL,SFPBUFFB3            ;Byte 3 of SFP
  681.     MOV    AH,0                ;Make into a word
  682.     SUB    AX,80H                ;Remove bias
  683.     MOV    FPTEMP1W11,AX            ;Its 16-bit 2's complement
  684.     RET
  685. SFP2TFP        ENDP
  686. ;-----------------------------------------------------------------------------
  687. ;Routine to convert from ASCII signed decimal to binary
  688. SGNDEC16IN    PROC    FAR
  689.     MOV    DX,0                ;Initialize DX as 0
  690.     MOV    CH,0                ;Sign flag
  691.     CALL    STD_IN                ;Look for sign
  692.     CMP    AL,'-'                ;Minus ?
  693.     JZ    SGNDEC16IN1            ;Store it
  694.     CMP    AL,'+'                ;Plus ?
  695.     JZ    SGNDEC16IN2            ;Ignore it
  696.     JMP    SGNDEC16IN3            ;Anything else gets used
  697. ;
  698. ;Set sign as negative
  699. SGNDEC16IN1:
  700.     MOV    CH,0FFH                ;0FFH is -1
  701. ;Normal loop
  702. SGNDEC16IN2:
  703.     CALL    STDIN                ;Digit comes in AL
  704. ;Already have a digit ?
  705. SGNDEC16IN3:
  706.     SUB    AL,30H                ;Subtract 30H
  707.     JL    SGNDEC16IN4            ;Check if too low
  708.     CMP    AL,9
  709.     JG    SGNDEC16IN4            ;Check if too high
  710.     CBW                    ;Convert to word
  711.     PUSH    CX                ;Save sign
  712.     PUSH    AX                ; and digit
  713.     MOV    AX,DX
  714.     MOV    CX,10                ;Multiplier of 10
  715.     MUL    CX                ;Multiply
  716.     MOV    DX,AX                ;Result in DX
  717.     POP    AX                ;Restore digit
  718.     ADD    DX,AX                ;Add in digit
  719.     POP    CX                ;Restore count
  720.     JMP    SGNDEC16IN2
  721. ;
  722. ;Resolve the sign
  723. SGNDEC16IN4:
  724.     CMP    CH,0                ;Is it there ?
  725.     JE    SGNDEC16IN_XIT            ;If not, skip
  726.     NEG    DX                ;It was negative
  727. SGNDEC16IN_XIT:
  728.     RET
  729. SGNDEC16IN    ENDP
  730. ;-----------------------------------------------------------------------------
  731. ;Routine to display floating point
  732. TDECSHOW    PROC    NEAR
  733. ;
  734. ;Output the sign
  735.     CMP    DECSIGN,0            ;Is it there ?
  736.     MOV    AL,' '                ;Space if not
  737.     JE    TDECSHOW1
  738. ;
  739. ;Output a minus sign
  740.     MOV    AL,'-'                ;Minus sign
  741. TDECSHOW1:
  742.     CALL    STD_OUT                ;Send it out
  743. ;
  744. ;Output the first digit and a decimal point
  745. TDECSHOW2:
  746.     LEA    SI,DECBUFF+21            ;Point to first digit
  747.     MOV    AL,[SI]                ;Get it
  748.     DEC    SI                ;Point to next digit
  749.     ADD    AL,30H                ;Make it ASCII
  750.     CALL    STD_OUT                ;Send it out
  751. ;
  752. ;Output the rest of the decimal string
  753.     MOV    CX,7                ;Only 7 more digits
  754. TDECSHOW3:
  755.     MOV    AL,[SI]                ;Get digit
  756.     DEC    SI                ;Point to next digit
  757.     ADD    AL,30H                ;Make ASCII
  758.     CALL    STD_OUT                ;Send it out
  759.     LOOP    TDECSHOW3
  760.     MOV    AL,'E'                ;E for exponent
  761.     CALL    STD_OUT                ;Send it
  762. ;
  763. ;Now the exponent
  764.     MOV    DX,DECEXP            ;Get exponent
  765.     CMP    DX,0                ;Check sign
  766.     MOV    AL,'+'                ;Plus sign
  767.     JGE    TDECSHOW_XIT            ;If non-negative
  768. ;
  769. ;If negative exponent
  770.     NEG    DX                ;Absolute value of exponent
  771.     MOV    AL,'-'                ;Minus sign
  772. TDECSHOW_XIT:
  773.     CALL    STD_OUT                ;Output sign of exponent
  774.     CALL    DEC16OUT            ;Output exponent
  775.     RET
  776. TDECSHOW    ENDP
  777. ;-----------------------------------------------------------------------------
  778. ;Routine to convert from temporary floating point to single precision
  779. TFP2SFP    PROC    NEAR
  780. ;
  781. ;Move mantissa
  782.     MOV    AX,FPTEMP1W4            ;Below word
  783.     RCL    AX,1                ;Carry for round up
  784.     MOV    AX,FPTEMP1W6            ;Low word
  785.     ADC    AX,0                ;Low word + carry
  786.     MOV    SFPBUFFW0,AX            ;Put in place
  787.     MOV    DX,AX                ;Check for zero
  788.     MOV    AX,FPTEMP1W8            
  789.     OR    DX,AX                ;Check this part, too
  790.     AND    AX,007FH            ;Just bottom 7 bits
  791.     MOV    SFPBUFFW2,AX            ;Put in place
  792. ;
  793. ;Move sign bit
  794.     MOV    AL,FPTEMP1B10            ;Byte 10 is sign
  795.     AND    AL,80H        
  796.     OR    SFPBUFFB2,AL            ;Bit 7 is sign
  797. ;
  798. ;Move exponent
  799.     MOV    AX,FPTEMP1W11            ;16-bit 2's complement exponent
  800.     CMP    AX,-128                ;Too low ?
  801.     JL    TFP2SFP2            ;Error message
  802.     CMP    AX,127                ;Too high ?
  803.     JG    TFP2SFP3            ;Error message
  804.     ADD    AX,80H                ;Bias
  805.     CMP    DX,0                ;Is mantissa 0 ?
  806.     JNE    TFP2SFP1
  807.     MOV    AL,0                ;Put biased byte back
  808. ;
  809. ;Normal return
  810. ;Show hex for debugging
  811.     LEA    SI,INTERNAL            ;Point to message
  812.     CALL    STDMSG_OUT            ;Send message
  813.     MOV    DX,SFPBUFFW2            ;Upper word
  814.     CALL    HEX16OUT            ;Show it
  815.     MOV    DX,SFPBUFFW0            ;Lower word
  816.     CALL    HEX16OUT            ;Show it
  817.     CALL    STD_SPACE            ;Skip space
  818.     CLC                    ;Clear carry
  819.     RET
  820. ;
  821. ;Underflow error
  822. TFP2SFP2:
  823.     LEA    SI,UNDERFLOW            ;Point to message
  824.     JMP    TFP2SFP4
  825. ;
  826. ;Overflow error
  827. TFP2SFP3:
  828.     LEA    SI,OVERFLOW            ;Point to message
  829.     JMP    TFP2SFP4
  830. TFP2SFP_XIT:
  831.     CALL    STDMSG_OUT            ;Send message
  832.     STC                    ;Set carry
  833.     RET
  834. TFP2SFP        ENDP
  835. ;-----------------------------------------------------------------------------
  836. ;_____________________________________________________________________________
  837. ;
  838. CODES    ENDS
  839. ;
  840.     END
  841. ;_____________________________________________________________________________
  842. ;>>>>> Physical EOF FLOATPT.ASM <<<<<
  843.