home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Rtl / Sys / FFMT.ASM < prev    next >
Encoding:
Assembly Source File  |  1999-08-11  |  16.3 KB  |  1,124 lines

  1.  
  2. ; *******************************************************
  3. ; *                            *
  4. ; *     Delphi Runtime Library                          *
  5. ; *    Floating point formatting routines        *
  6. ; *                            *
  7. ; *    Copyright (c) 1995,98 Inprise Corporation    *
  8. ; *                            *
  9. ; *******************************************************
  10.  
  11.     TITLE    FFMT
  12.  
  13.     .386
  14.     .MODEL    FLAT
  15.  
  16.     INCLUDE    SE.ASM
  17.  
  18. ; TFloatRec layout
  19.  
  20. fdExponent    EQU    (WORD PTR 0)
  21. fdNegative    EQU    (BYTE PTR 2)
  22. fdDigits    EQU    (BYTE PTR 3)
  23. fdRecSize    EQU    24
  24.  
  25. ; TFloatValue constants
  26.  
  27. fvExtended    EQU    0
  28. fvCurrency    EQU    1
  29.  
  30. ; TFloatFormat constants
  31.  
  32. ffGeneral    EQU    0
  33. ffExponent    EQU    1
  34. ffFixed        EQU    2
  35. ffNumber    EQU    3
  36. ffCurrency    EQU    4
  37.  
  38. ; 1E18 as a 64-bit integer
  39.  
  40. Const1E18Lo    EQU    0A7640000H
  41. Const1E18Hi    EQU    00DE0B6B3H
  42.  
  43. ; Externals
  44.  
  45.     EXTRN    FPower10:NEAR
  46.     EXTRN    CurrencyString:DWORD
  47.     EXTRN    CurrencyFormat:BYTE
  48.     EXTRN    NegCurrFormat:BYTE
  49.     EXTRN    ThousandSeparator:BYTE
  50.     EXTRN    DecimalSeparator:BYTE
  51.  
  52. ; Publics
  53.  
  54.     PUBLIC    FloatToText,FloatToTextFmt,FloatToDecimal,TextToFloat
  55.  
  56.     .CODE
  57.  
  58. ; Constants
  59.  
  60. DCon10        DD    10
  61. DCon100        DD    100
  62. DCon1000    DD    1000
  63. DCon10000    DD    10000
  64.  
  65. FCon1E18    DT    1E18
  66.  
  67. ; 8087 control word
  68. ; Infinity control  = 1 Affine
  69. ; Rounding Control  = 0 Round to nearest or even
  70. ; Precision Control = 3 64 bits
  71. ; All interrupts masked
  72.  
  73. CWNear        DW    133FH
  74.  
  75. ; INF and NAN strings
  76.  
  77. INFNAN        DB    'INFNAN'
  78.  
  79. ; function FloatToText(Buffer: PChar; const Value; ValueType: TFloatValue;
  80. ;   Format: TFloatFormat; Precision, Digits: Integer): Integer;
  81.  
  82. FloatToText:
  83.  
  84.     ARG    BufferArg,DWORD,1
  85.     ARG    Value,DWORD,1
  86.     ARG    ValueType,BYTE,4
  87.     ARG    Format,BYTE,4
  88.     ARG    Precision,DWORD,1
  89.     ARG    Digits,DWORD,1
  90.     LOC    Buffer,DWORD,1
  91.     LOC    FloatRec,BYTE,fdRecSize
  92.  
  93.     ENTRY    FAR
  94.     PUSH    EDI
  95.     PUSH    ESI
  96.     PUSH    EBX
  97.     MOV    Buffer,EAX
  98.     MOV    EAX,19
  99.     CMP    CL,fvExtended
  100.     JNE    @@2
  101.     MOV    EAX,Precision
  102.     CMP    EAX,2
  103.     JGE    @@1
  104.     MOV    EAX,2
  105. @@1:    CMP    EAX,18
  106.     JLE    @@2
  107.     MOV    EAX,18
  108. @@2:    MOV    Precision,EAX
  109.     PUSH    EAX
  110.     MOV    EAX,9999
  111.     CMP    Format,ffFixed
  112.     JB    @@3
  113.     MOV    EAX,Digits
  114. @@3:    PUSH    EAX
  115.     LEA    EAX,FloatRec
  116.     CALL    FloatToDecimal
  117.     MOV    EDI,Buffer
  118.     MOVZX    EAX,FloatRec.fdExponent
  119.     SUB    EAX,7FFFH
  120.     CMP    EAX,2
  121.     JAE    @@4
  122.         MOV     ECX, EAX
  123.         CALL    PutSign
  124.     LEA    ESI,INFNAN[ECX+ECX*2]
  125.     MOV    ECX,3
  126.     REP    MOVSB
  127.     JMP    @@7
  128. @@4:    LEA    ESI,FloatRec.fdDigits
  129.     MOVZX    EBX,Format
  130.     CMP    BL,ffExponent
  131.     JE    @@6
  132.     CMP    BL,ffCurrency
  133.     JA    @@5
  134.     MOVSX    EAX,FloatRec.fdExponent
  135.     CMP    EAX,Precision
  136.     JLE    @@6
  137. @@5:    MOV    BL,ffGeneral
  138. @@6:    CALL    DWORD PTR FormatVector[EBX*4]
  139. @@7:    MOV    EAX,EDI
  140.     SUB    EAX,Buffer
  141.     POP    EBX
  142.     POP    ESI
  143.     POP    EDI
  144.     EXIT
  145.  
  146. FormatVector    LABEL    DWORD
  147.  
  148.     DD    PutFGeneral
  149.     DD    PutFExponent
  150.     DD    PutFFixed
  151.     DD    PutFNumber
  152.     DD    PutFCurrency
  153.  
  154. ; Get digit or '0' if at end of digit string
  155.  
  156. GetDigit:
  157.  
  158.     LODSB
  159.     OR    AL,AL
  160.     JNE    @@1
  161.     MOV    AL,'0'
  162.     DEC    ESI
  163. @@1:    RET
  164.  
  165. ; Store '-' if number is negative
  166.  
  167. PutSign:
  168.  
  169.     CMP    FloatRec.fdNegative,0
  170.     JE    @@1
  171.     MOV    AL,'-'
  172.     STOSB
  173. @@1:    RET
  174.  
  175. ; Convert number using ffGeneral format
  176.  
  177. PutFGeneral:
  178.  
  179.     CALL    PutSign
  180.     MOVSX    ECX,FloatRec.fdExponent
  181.     XOR    EDX,EDX
  182.     CMP    ECX,Precision
  183.     JG    @@1
  184.     CMP    ECX,-3
  185.     JL    @@1
  186.     OR    ECX,ECX
  187.     JG    @@2
  188.     MOV    AL,'0'
  189.     STOSB
  190.     CMP    BYTE PTR [ESI],0
  191.     JE    @@6
  192.     MOV    AL,DecimalSeparator
  193.     STOSB
  194.     NEG    ECX
  195.     MOV    AL,'0'
  196.     REP    STOSB
  197.     JMP    @@3
  198. @@1:    MOV    ECX,1
  199.     INC    EDX
  200. @@2:    LODSB
  201.     OR    AL,AL
  202.     JE    @@4
  203.     STOSB
  204.     LOOP    @@2
  205.     LODSB
  206.     OR    AL,AL
  207.     JE    @@5
  208.     MOV    AH,AL
  209.     MOV    AL,DecimalSeparator
  210.     STOSW
  211. @@3:    LODSB
  212.     OR    AL,AL
  213.     JE    @@5
  214.     STOSB
  215.     JMP    @@3
  216. @@4:    MOV    AL,'0'
  217.     REP    STOSB
  218. @@5:    OR    EDX,EDX
  219.     JE    @@6
  220.     XOR    EAX,EAX
  221.     XOR    ECX,ECX
  222.     JMP    PutFloatExp
  223. @@6:    RET
  224.  
  225. ; Convert number using ffExponent format
  226.  
  227. PutFExponent:
  228.  
  229.     CALL    PutSign
  230.     CALL    GetDigit
  231.     MOV    AH,DecimalSeparator
  232.     STOSW
  233.     MOV    ECX,Precision
  234.     DEC    ECX
  235. @@1:    CALL    GetDigit
  236.     STOSB
  237.     LOOP    @@1
  238.     MOV    AH,'+'
  239.     MOV    ECX,Digits
  240.     CMP    ECX,4
  241.     JB    PutFloatExp
  242.     XOR    ECX,ECX
  243. ;    JMP    PutFloatExp
  244.  
  245. ; Store exponent
  246. ; In    AH  = Positive sign character ('+' or 0)
  247. ;    ECX = Minimum number of digits (0..4)
  248.  
  249. PutFloatExp:
  250.  
  251.     MOV    AL,'E'
  252.     MOV    BL,FloatRec.fdDigits
  253.     MOVSX    EDX,FloatRec.fdExponent
  254.     DEC    EDX
  255. ;    JMP    PutExponent
  256.  
  257. ; Store exponent
  258. ; In    AL  = Exponent character ('E' or 'e')
  259. ;    AH  = Positive sign character ('+' or 0)
  260. ;    BL  = Zero indicator
  261. ;    ECX = Minimum number of digits (0..4)
  262. ;    EDX = Exponent
  263.  
  264. PutExponent:
  265.  
  266.     STOSB
  267.     OR    BL,BL
  268.     JNE    @@0
  269.     XOR    EDX,EDX
  270.     JMP    @@1
  271. @@0:    OR    EDX,EDX
  272.     JGE    @@1
  273.     MOV    AL,'-'
  274.     NEG    EDX
  275.     JMP    @@2
  276. @@1:    OR    AH,AH
  277.     JE    @@3
  278.     MOV    AL,AH
  279. @@2:    STOSB
  280. @@3:    XCHG    EAX,EDX
  281.     PUSH    EAX
  282.     MOV    EBX,ESP
  283. @@4:    XOR    EDX,EDX
  284.     DIV    DCon10
  285.     ADD    DL,'0'
  286.     MOV    [EBX],DL
  287.     INC    EBX
  288.     DEC    ECX
  289.     OR    EAX,EAX
  290.     JNE    @@4
  291.     OR    ECX,ECX
  292.     JG    @@4
  293. @@5:    DEC    EBX
  294.     MOV    AL,[EBX]
  295.     STOSB
  296.     CMP    EBX,ESP
  297.     JNE    @@5
  298.     POP    EAX
  299.     RET
  300.  
  301. ; Convert number using ffFixed or ffNumber format
  302.  
  303. PutFFixed:
  304. PutFNumber:
  305.  
  306.     CALL    PutSign
  307.  
  308. ; Store number in fixed point format
  309.  
  310. PutNumber:
  311.  
  312.     MOV    EDX,Digits
  313.     CMP    EDX,18
  314.     JB    @@1
  315.     MOV    EDX,18
  316. @@1:    MOVSX    ECX,FloatRec.fdExponent
  317.     OR    ECX,ECX
  318.     JG    @@2
  319.     MOV    AL,'0'
  320.     STOSB
  321.     JMP    @@4
  322. @@2:    XOR    EBX,EBX
  323.     CMP    Format,ffFixed
  324.     JE    @@3
  325.     MOV    EAX,ECX
  326.     DEC    EAX
  327.     MOV    BL,3
  328.     DIV    BL
  329.     MOV    BL,AH
  330.     INC    EBX
  331. @@3:    CALL    GetDigit
  332.     STOSB
  333.     DEC    ECX
  334.     JE    @@4
  335.     DEC    EBX
  336.     JNE    @@3
  337.     MOV    AL,ThousandSeparator
  338.     STOSB
  339.     MOV    BL,3
  340.     JMP    @@3
  341. @@4:    OR    EDX,EDX
  342.     JE    @@7
  343.     MOV    AL,DecimalSeparator
  344.     STOSB
  345.     JECXZ    @@6
  346.     MOV    AL,'0'
  347. @@5:    STOSB
  348.     DEC    EDX
  349.     JE    @@7
  350.     INC    ECX
  351.     JNE    @@5
  352. @@6:    CALL    GetDigit
  353.     STOSB
  354.     DEC    EDX
  355.     JNE    @@6
  356. @@7:    RET
  357.  
  358. ; Convert number using ffCurrency format
  359.  
  360. PutFCurrency:
  361.  
  362.     XOR    EBX,EBX
  363.     MOV    BL,CurrencyFormat
  364.     MOV    ECX,0003H
  365.     CMP    FloatRec.fdNegative,0
  366.     JE    @@1
  367.     MOV    BL,NegCurrFormat
  368.     MOV    ECX,040FH
  369. @@1:    CMP    BL,CL
  370.     JBE    @@2
  371.     MOV    BL,CL
  372. @@2:    ADD    BL,CH
  373.     LEA    EBX,MoneyFormats[EBX+EBX*4]
  374.     MOV    ECX,5
  375. @@10:    MOV    AL,[EBX]
  376.     CMP    AL,'@'
  377.     JE    @@14
  378.     PUSH    ECX
  379.     PUSH    EBX
  380.     CMP    AL,'$'
  381.     JE    @@11
  382.     CMP    AL,'*'
  383.     JE    @@12
  384.     STOSB
  385.     JMP    @@13
  386. @@11:    CALL    PutCurSym
  387.     JMP    @@13
  388. @@12:    CALL    PutNumber
  389. @@13:    POP    EBX
  390.     POP    ECX
  391.     INC    EBX
  392.     LOOP    @@10
  393. @@14:    RET
  394.  
  395. ; Store currency symbol string
  396.  
  397. PutCurSym:
  398.  
  399.     PUSH    ESI
  400.     MOV    ESI,CurrencyString
  401.     TEST    ESI,ESI
  402.     JE    @@1
  403.     MOV    ECX,[ESI-4]
  404.     REP    MOVSB
  405. @@1:    POP    ESI
  406.     RET
  407.  
  408. ; Currency formatting templates
  409.  
  410. MoneyFormats    LABEL    BYTE
  411.  
  412.     DB    '$*@@@'
  413.     DB    '*$@@@'
  414.     DB      '$ *@@'
  415.     DB    '* $@@'
  416.     DB    '($*)@'
  417.     DB    '-$*@@'
  418.     DB    '$-*@@'
  419.     DB    '$*-@@'
  420.     DB    '(*$)@'
  421.     DB    '-*$@@'
  422.     DB    '*-$@@'
  423.     DB    '*$-@@'
  424.     DB    '-* $@'
  425.     DB    '-$ *@'
  426.     DB    '* $-@'
  427.     DB    '$ *-@'
  428.     DB    '$ -*@'
  429.     DB    '*- $@'
  430.     DB    '($ *)'
  431.     DB    '(* $)'
  432.  
  433. ; function FloatToTextFmt(Buffer: PChar; const Value; ValueType: TValueType;
  434. ;   Format: PChar): Integer;
  435.  
  436. FloatToTextFmt:
  437.  
  438.     ARG    BufferArg,DWORD,1
  439.     ARG    Value,DWORD,1
  440.     ARG    ValueType,BYTE,4
  441.     ARG    Format,DWORD,1
  442.     LOC    Buffer,DWORD,1
  443.     LOC    ThousandSep,BYTE,4
  444.     LOC    Scientific,BYTE,4
  445.     LOC    Section,DWORD,1
  446.     LOC    DigitCount,DWORD,1
  447.     LOC    DecimalIndex,DWORD,1
  448.     LOC    FirstDigit,DWORD,1
  449.     LOC    LastDigit,DWORD,1
  450.     LOC    DigitPlace,DWORD,1
  451.     LOC    DigitDelta,DWORD,1
  452.     LOC    FloatRec,BYTE,fdRecSize
  453.  
  454.     ENTRY    FAR
  455.     PUSH    EDI
  456.     PUSH    ESI
  457.     PUSH    EBX
  458.     MOV    Buffer,EAX
  459.     MOV    EDI,EDX
  460.     MOV    EBX,ECX
  461.     MOV    ECX,2
  462.     CMP    BL,fvExtended
  463.     JE    @@1
  464.     MOV    EAX,[EDI].d0
  465.     OR    EAX,[EDI].d4
  466.     JE    @@2
  467.     MOV    ECX,[EDI].d4
  468.     SHR    ECX,31
  469.     JMP    @@2
  470. @@1:    MOVZX    EAX,[EDI].w8
  471.     OR    EAX,[EDI].d0
  472.     OR    EAX,[EDI].d4
  473.     JE    @@2
  474.     MOVZX    ECX,[EDI].w8
  475.     SHR    ECX,15
  476. @@2:    CALL    FindSection
  477.     JE    @@5
  478.     CALL    ScanSection
  479.     MOV    EAX,DigitCount
  480.     MOV    EDX,9999
  481.     CMP    Scientific,0
  482.     JNE    @@3
  483.     SUB    EAX,DecimalIndex
  484.     MOV    EDX,EAX
  485.     MOV    EAX,18
  486. @@3:    PUSH    EAX
  487.     PUSH    EDX
  488.     LEA    EAX,FloatRec
  489.     MOV    EDX,EDI
  490.     MOV    ECX,EBX
  491.     CALL    FloatToDecimal
  492.     MOV    AX,FloatRec.fdExponent
  493.     CMP    AX,8000H
  494.     JE    @@5
  495.     CMP    AX,7FFFH
  496.     JE    @@5
  497.     CMP    BL,fvExtended
  498.     JNE    @@6
  499.     CMP    AX,18
  500.     JLE    @@6
  501.     CMP    Scientific,0
  502.     JNE    @@6
  503. @@5:    PUSH    ffGeneral
  504.     PUSH    15
  505.     PUSH    0
  506.     MOV    EAX,Buffer
  507.     MOV    EDX,EDI
  508.     MOV    ECX,EBX
  509.     CALL    FloatToText
  510.     JMP    @@8
  511. @@6:    CMP    FloatRec.fdDigits,0
  512.     JNE    @@7
  513.     MOV    ECX,2
  514.     CALL    FindSection
  515.     JE    @@5
  516.     CMP    ESI,Section
  517.     JE    @@7
  518.     CALL    ScanSection
  519. @@7:    CALL    ApplyFormat
  520. @@8:    POP    EBX
  521.     POP    ESI
  522.     POP    EDI
  523.     EXIT
  524.  
  525. ; Find format section
  526. ; In    ECX = Section index
  527. ; Out    ESI = Section offset
  528. ;    ZF  = 1 if section is empty
  529.  
  530. FindSection:
  531.  
  532.     MOV    ESI,Format
  533.     JECXZ    @@2
  534. @@1:    LODSB
  535.     CMP    AL,"'"
  536.     JE    @@4
  537.     CMP    AL,'"'
  538.     JE    @@4
  539.     OR    AL,AL
  540.     JE    @@2
  541.     CMP    AL,';'
  542.     JNE    @@1
  543.     LOOP    @@1
  544.     MOV    AL,[ESI]
  545.     OR    AL,AL
  546.     JE    @@2
  547.     CMP    AL,';'
  548.     JNE    @@3
  549. @@2:    MOV    ESI,Format
  550.     MOV    AL,[ESI]
  551.     OR    AL,AL
  552.     JE    @@3
  553.     CMP    AL,';'
  554. @@3:    RET
  555. @@4:    MOV    AH,AL
  556. @@5:    LODSB
  557.     CMP    AL,AH
  558.     JE    @@1
  559.     OR    AL,AL
  560.     JNE    @@5
  561.     JMP    @@2
  562.  
  563. ; Scan format section
  564.  
  565. ScanSection:
  566.  
  567.     PUSH    EBX
  568.     MOV    Section,ESI
  569.     MOV    EBX,32767
  570.     XOR    ECX,ECX
  571.     XOR    EDX,EDX
  572.     MOV    DecimalIndex,-1
  573.     MOV    ThousandSep,DL
  574.     MOV    Scientific,DL
  575. @@1:    LODSB
  576. @@2:    CMP    AL,'#'
  577.     JE    @@10
  578.     CMP    AL,'0'
  579.     JE    @@11
  580.     CMP    AL,'.'
  581.     JE    @@13
  582.     CMP    AL,','
  583.     JE    @@14
  584.     CMP    AL,"'"
  585.     JE    @@15
  586.     CMP    AL,'"'
  587.     JE    @@15
  588.     CMP    AL,'E'
  589.     JE    @@20
  590.     CMP    AL,'e'
  591.     JE    @@20
  592.     CMP    AL,';'
  593.     JE    @@30
  594.     OR    AL,AL
  595.     JNE    @@1
  596.     JMP    @@30
  597. @@10:    INC    EDX
  598.     JMP    @@1
  599. @@11:    CMP    EDX,EBX
  600.     JGE    @@12
  601.     MOV    EBX,EDX
  602. @@12:    INC    EDX
  603.     MOV    ECX,EDX
  604.     JMP    @@1
  605. @@13:    CMP    DecimalIndex,-1
  606.     JNE    @@1
  607.     MOV    DecimalIndex,EDX
  608.     JMP    @@1
  609. @@14:    MOV    ThousandSep,1
  610.     JMP    @@1
  611. @@15:    MOV    AH,AL
  612. @@16:    LODSB
  613.     CMP    AL,AH
  614.     JE    @@1
  615.     OR    AL,AL
  616.     JNE    @@16
  617.     JMP    @@30
  618. @@20:    LODSB
  619.     CMP    AL,'-'
  620.     JE    @@21
  621.     CMP    AL,'+'
  622.     JNE    @@2
  623. @@21:    MOV    Scientific,1
  624. @@22:    LODSB
  625.     CMP    AL,'0'
  626.     JE    @@22
  627.     JMP    @@2
  628. @@30:    MOV    DigitCount,EDX
  629.     CMP    DecimalIndex,-1
  630.     JNE    @@31
  631.     MOV    DecimalIndex,EDX
  632. @@31:    MOV    EAX,DecimalIndex
  633.     SUB    EAX,ECX
  634.     JLE    @@32
  635.     XOR    EAX,EAX
  636. @@32:    MOV    LastDigit,EAX
  637.     MOV    EAX,DecimalIndex
  638.     SUB    EAX,EBX
  639.     JGE    @@33
  640.     XOR    EAX,EAX
  641. @@33:    MOV    FirstDigit,EAX
  642.     POP    EBX
  643.     RET
  644.  
  645. ; Apply format string
  646.  
  647. ApplyFormat:
  648.  
  649.     CMP    Scientific,0
  650.     JE    @@1
  651.     MOV    EAX,DecimalIndex
  652.     XOR    EDX,EDX
  653.     JMP    @@3
  654. @@1:    MOVSX    EAX,FloatRec.fdExponent
  655.     CMP    EAX,DecimalIndex
  656.     JG    @@2
  657.     MOV    EAX,DecimalIndex
  658. @@2:    MOVSX    EDX,FloatRec.fdExponent
  659.     SUB    EDX,DecimalIndex
  660. @@3:    MOV    DigitPlace,EAX
  661.     MOV    DigitDelta,EDX
  662.     MOV    ESI,Section
  663.     MOV    EDI,Buffer
  664.     LEA    EBX,FloatRec.fdDigits
  665.     CMP    FloatRec.fdNegative,0
  666.     JE    @@10
  667.     CMP    ESI,Format
  668.     JNE    @@10
  669.     MOV    AL,'-'
  670.     STOSB
  671. @@10:    LODSB
  672.     CMP    AL,'#'
  673.     JE    @@20
  674.     CMP    AL,'0'
  675.     JE    @@20
  676.     CMP    AL,'.'
  677.     JE    @@10
  678.     CMP    AL,','
  679.     JE    @@10
  680.     CMP    AL,"'"
  681.     JE    @@25
  682.     CMP    AL,'"'
  683.     JE    @@25
  684.     CMP    AL,'E'
  685.     JE    @@30
  686.     CMP    AL,'e'
  687.     JE    @@30
  688.     CMP    AL,';'
  689.     JE    @@40
  690.     OR    AL,AL
  691.     JE    @@40
  692. @@11:    STOSB
  693.     JMP    @@10
  694. @@20:    CALL    PutFmtDigit
  695.     JMP    @@10
  696. @@25:    MOV    AH,AL
  697. @@26:    LODSB
  698.     CMP    AL,AH
  699.     JE    @@10
  700.     OR    AL,AL
  701.     JE    @@40
  702.     STOSB
  703.     JMP    @@26
  704. @@30:    MOV    AH,[ESI]
  705.     CMP    AH,'+'
  706.     JE    @@31
  707.     CMP    AH,'-'
  708.     JNE    @@11
  709.     XOR    AH,AH
  710. @@31:    MOV    ECX,-1
  711. @@32:    INC    ECX
  712.     INC    ESI
  713.     CMP    [ESI].b0,'0'
  714.     JE    @@32
  715.     CMP    ECX,4
  716.     JB    @@33
  717.     MOV    ECX,4
  718. @@33:    PUSH    EBX
  719.     MOV    BL,FloatRec.fdDigits
  720.     MOVSX    EDX,FloatRec.fdExponent
  721.     SUB    EDX,DecimalIndex
  722.     CALL    PutExponent
  723.     POP    EBX
  724.     JMP    @@10
  725. @@40:    MOV    EAX,EDI
  726.     SUB    EAX,Buffer
  727.     RET
  728.  
  729. ; Store formatted digit
  730.  
  731. PutFmtDigit:
  732.  
  733.     CMP    DigitDelta,0
  734.     JE    @@3
  735.     JL    @@2
  736. @@1:    CALL    @@3
  737.     DEC    DigitDelta
  738.     JNE    @@1
  739.     JMP    @@3
  740. @@2:    INC    DigitDelta
  741.     MOV    EAX,DigitPlace
  742.     CMP    EAX,FirstDigit
  743.     JLE    @@4
  744.     JMP    @@7
  745. @@3:    MOV    AL,[EBX]
  746.     INC    EBX
  747.     OR    AL,AL
  748.     JNE    @@5
  749.     DEC    EBX
  750.     MOV    EAX,DigitPlace
  751.     CMP    EAX,LastDigit
  752.     JLE    @@7
  753. @@4:    MOV    AL,'0'
  754. @@5:    CMP    DigitPlace,0
  755.     JNE    @@6
  756.     MOV    AH,AL
  757.     MOV    AL,DecimalSeparator
  758.     STOSW
  759.     JMP    @@7
  760. @@6:    STOSB
  761.     CMP    ThousandSep,0
  762.     JE    @@7
  763.     MOV    EAX,DigitPlace
  764.     CMP    EAX,1
  765.     JLE    @@7
  766.     MOV    DL,3
  767.     DIV    DL
  768.     CMP    AH,1
  769.     JNE    @@7
  770.     MOV    AL,ThousandSeparator
  771.     STOSB
  772. @@7:    DEC    DigitPlace
  773.     RET
  774.  
  775. ; procedure FloatToDecimal(var Result: TFloatDecimal; const Value;
  776. ;   ValueType: TValueType; Precision, Decimals: Integer);
  777.  
  778. FloatToDecimal:
  779.  
  780.     ARG    Result,DWORD,1
  781.     ARG    Value,DWORD,1
  782.     ARG    ValueType,BYTE,4
  783.     ARG    Precision,DWORD,1
  784.     ARG    Decimals,DWORD,1
  785.     LOC    StatWord,WORD,2
  786.     LOC    Exponent,DWORD,1
  787.     LOC    Temp,QWORD,1
  788.     LOC    BCDValue,TBYTE,1
  789.  
  790.     ENTRY   FAR
  791.     PUSH    EDI
  792.     PUSH    ESI
  793.     PUSH    EBX
  794.     MOV    EBX,EAX
  795.     MOV    ESI,EDX
  796.     CMP    CL,fvExtended
  797.     JE    @@1
  798.     CALL    CurrToDecimal
  799.     JMP    @@2
  800. @@1:    CALL    ExtToDecimal
  801. @@2:    POP    EBX
  802.     POP    ESI
  803.     POP    EDI
  804.     EXIT
  805.  
  806. ; Convert Extended to decimal
  807.  
  808. ExtToDecimal:
  809.  
  810.     MOV    AX,[ESI].w8
  811.     MOV    EDX,EAX
  812.     AND    EAX,7FFFH
  813.     JE    @@1
  814.     CMP    EAX,7FFFH
  815.     JNE    @@10
  816. ; check for special values (INF, NAN)
  817.     TEST    [ESI].w6,8000H
  818.     JZ    @@2
  819. ; any significand bit set = NAN
  820. ; all significand bits clear = INF
  821.         CMP     dword ptr [ESI], 0
  822.         JNZ     @@0
  823.         CMP     dword ptr [ESI+4], 80000000H
  824.         JZ      @@2
  825. @@0:    INC    EAX
  826. @@1:    XOR    EDX,EDX
  827. @@2:    MOV    [EBX].fdDigits,0
  828.     JMP    @@31
  829. @@10:    FLD    TBYTE PTR [ESI]
  830.     SUB    EAX,3FFFH
  831.     IMUL    EAX,19728
  832.     SAR    EAX,16
  833.     INC    EAX
  834.     MOV    Exponent,EAX
  835.     MOV    EAX,18
  836.     SUB    EAX,Exponent
  837.     FABS
  838.     CALL    FPower10
  839.     FRNDINT
  840.     FLD    FCon1E18
  841.     FCOMP
  842.     FSTSW    StatWord
  843.     FWAIT
  844.     TEST    StatWord,mC0+mC3
  845.     JE    @@11
  846.     FIDIV    DCon10
  847.     INC    Exponent
  848. @@11:    FBSTP    BCDValue
  849.     LEA    EDI,[EBX].fdDigits
  850.     MOV    EDX,9
  851.     FWAIT
  852. @@12:    MOV    AL,BCDValue[EDX-1].b0
  853.     MOV    AH,AL
  854.     SHR    AL,4
  855.     AND    AH,0FH
  856.     ADD    AX,'00'
  857.     STOSW
  858.     DEC    EDX
  859.     JNE    @@12
  860.     XOR    AL,AL
  861.     STOSB
  862. @@20:    MOV    EDI,Exponent
  863.     ADD    EDI,Decimals
  864.     JNS    @@21
  865.     XOR    EAX,EAX
  866.     JMP    @@1
  867. @@21:    CMP    EDI,Precision
  868.     JB    @@22
  869.     MOV    EDI,Precision
  870. @@22:    CMP    EDI,18
  871.     JAE    @@26
  872.     CMP    [EBX].fdDigits[EDI],'5'
  873.     JB    @@25
  874. @@23:    MOV    [EBX].fdDigits[EDI],0
  875.     DEC    EDI
  876.     JS    @@24
  877.     INC    [EBX].fdDigits[EDI]
  878.     CMP    [EBX].fdDigits[EDI],'9'
  879.     JA    @@23
  880.     JMP    @@30
  881. @@24:    MOV    [EBX].fdDigits.w0,'1'
  882.     INC    Exponent
  883.     JMP    @@30
  884. @@26:    MOV    EDI,18
  885. @@25:    MOV    [EBX].fdDigits[EDI],0
  886.     DEC    EDI
  887.     JS    @@32
  888.     CMP    [EBX].fdDigits[EDI],'0'
  889.     JE    @@25
  890. @@30:    MOV    DX,[ESI].w8
  891. @@30a:MOV    EAX,Exponent
  892. @@31:    SHR    DX,15
  893.     MOV    [EBX].fdExponent,AX
  894.     MOV    [EBX].fdNegative,DL
  895.     RET
  896. @@32: XOR EDX,EDX
  897.       JMP @@30a
  898.  
  899.  
  900. ; Convert Currency to decimal
  901.  
  902. CurrToDecimal:
  903.  
  904.     MOV    EAX,[ESI].d0
  905.     MOV    EDX,[ESI].d4
  906.     MOV    ECX,EAX
  907.     OR    ECX,EDX
  908.     JE    @@20
  909.     OR    EDX,EDX
  910.     JNS    @@1
  911.     NEG    EDX
  912.     NEG    EAX
  913.     SBB    EDX,0
  914. @@1:    XOR    ECX,ECX
  915.     MOV    EDI,Decimals
  916.     OR    EDI,EDI
  917.     JGE    @@2
  918.     XOR    EDI,EDI
  919. @@2:    CMP    EDI,4
  920.     JL    @@4
  921.     MOV    EDI,4
  922. @@3:    INC    ECX
  923.     SUB    EAX,Const1E18Lo
  924.     SBB    EDX,Const1E18Hi
  925.     JNC    @@3
  926.     DEC    ECX
  927.     ADD    EAX,Const1E18Lo
  928.     ADC    EDX,Const1E18Hi
  929. @@4:    MOV    Temp.d0,EAX
  930.     MOV    Temp.d4,EDX
  931.     FILD    Temp
  932.     MOV    EDX,EDI
  933.     MOV    EAX,4
  934.     SUB    EAX,EDX
  935.     JE    @@5
  936.     FIDIV    DCon10[EAX*4-4]
  937. @@5:    FBSTP    BCDValue
  938.     LEA    EDI,[EBX].fdDigits
  939.     FWAIT
  940.     OR    ECX,ECX
  941.     JNE    @@11
  942.     MOV    ECX,9
  943. @@10:    MOV    AL,BCDValue[ECX-1].b0
  944.     MOV    AH,AL
  945.     SHR    AL,4
  946.     JNE    @@13
  947.     MOV    AL,AH
  948.     AND    AL,0FH
  949.     JNE    @@14
  950.     DEC    ECX
  951.     JNE    @@10
  952.     JMP    @@20
  953. @@11:    MOV    AL,CL
  954.     ADD    AL,'0'
  955.     STOSB
  956.     MOV    ECX,9
  957. @@12:    MOV    AL,BCDValue[ECX-1].b0
  958.     MOV    AH,AL
  959.     SHR    AL,4
  960. @@13:    ADD    AL,'0'
  961.     STOSB
  962.     MOV    AL,AH
  963.     AND    AL,0FH
  964. @@14:    ADD    AL,'0'
  965.     STOSB
  966.     DEC    ECX
  967.     JNE    @@12
  968.     MOV    EAX,EDI
  969.     LEA    ECX,[EBX].fdDigits[EDX]
  970.     SUB    EAX,ECX
  971. @@15:    MOV    BYTE PTR [EDI],0
  972.     DEC    EDI
  973.     CMP    BYTE PTR [EDI],'0'
  974.     JE    @@15
  975.     MOV    EDX,[ESI].d4
  976.     SHR    EDX,31
  977.     JMP    @@21
  978. @@20:    XOR    EAX,EAX
  979.     XOR    EDX,EDX
  980.     MOV    [EBX].fdDigits,AL
  981. @@21:    MOV    [EBX].fdExponent,AX
  982.     MOV    [EBX].fdNegative,DL
  983.     RET
  984.  
  985. ; function TextToFloat(var Buffer; var Value;
  986. ;   ValueType: TFloatValue): Boolean;
  987.  
  988. TextToFloat:
  989.  
  990.     ARG    Buffer,DWORD,1
  991.     ARG    Value,DWORD,1
  992.     ARG    ValueType,BYTE,4
  993.     LOC    Temp,DWORD,1
  994.     LOC    CtrlWord,WORD,1
  995.  
  996.     ENTRY    FAR
  997.     PUSH    EDI
  998.     PUSH    ESI
  999.     PUSH    EBX
  1000.     MOV    ESI,EAX
  1001.     MOV    EDI,EDX
  1002.     MOV    EBX,ECX
  1003.     FSTCW    CtrlWord
  1004.     FCLEX
  1005.     FLDCW    CWNear
  1006.     FLDZ
  1007.     CALL    SkipBlanks
  1008.     MOV    BH,[ESI]
  1009.     CMP    BH,'+'
  1010.     JE    @@1
  1011.     CMP    BH,'-'
  1012.     JNE    @@2
  1013. @@1:    INC    ESI
  1014. @@2:    MOV    ECX,ESI
  1015.     CALL    GetDigitStr
  1016.     XOR    EDX,EDX
  1017.     MOV    AL,[ESI]
  1018.     CMP    AL,DecimalSeparator
  1019.     JNE    @@3
  1020.     INC    ESI
  1021.     CALL    GetDigitStr
  1022.     NEG    EDX
  1023. @@3:    CMP    ECX,ESI
  1024.     JE    @@9
  1025.     MOV    AL,[ESI]
  1026.     AND    AL,0DFH
  1027.     CMP    AL,'E'
  1028.     JNE    @@4
  1029.     INC    ESI
  1030.     PUSH    EDX
  1031.     CALL    GetExponent
  1032.     POP    EAX
  1033.     ADD    EDX,EAX
  1034. @@4:    CALL    SkipBlanks
  1035.     CMP    BYTE PTR [ESI],0
  1036.     JNE    @@9
  1037.     MOV    EAX,EDX
  1038.     CMP    BL,fvCurrency
  1039.     JNE    @@5
  1040.     ADD    EAX,4
  1041. @@5:    CALL    FPower10
  1042.     CMP    BH,'-'
  1043.     JNE    @@6
  1044.     FCHS
  1045. @@6:    CMP    BL,fvExtended
  1046.     JE    @@7
  1047.     FISTP    QWORD PTR [EDI]
  1048.     JMP    @@8
  1049. @@7:    FSTP    TBYTE PTR [EDI]
  1050. @@8:    FSTSW    AX
  1051.     TEST    AX,mIE+mOE
  1052.     JNE    @@10
  1053.     MOV    AL,1
  1054.     JMP    @@11
  1055. @@9:    FSTP    ST(0)
  1056. @@10:    XOR    EAX,EAX
  1057. @@11:    FCLEX
  1058.     FLDCW    CtrlWord
  1059.     FWAIT
  1060.     POP    EBX
  1061.     POP    ESI
  1062.     POP    EDI
  1063.     EXIT
  1064.  
  1065. ; Skip blanks
  1066.  
  1067. SkipBlanks:
  1068.  
  1069. @@1:    LODSB
  1070.     OR    AL,AL
  1071.     JE    @@2
  1072.     CMP    AL,' '
  1073.     JE    @@1
  1074. @@2:    DEC    ESI
  1075.     RET
  1076.  
  1077. ; Process string of digits
  1078. ; Out    EDX = Digit count
  1079.  
  1080. GetDigitStr:
  1081.  
  1082.     XOR    EAX,EAX
  1083.     XOR    EDX,EDX
  1084. @@1:    LODSB
  1085.     SUB    AL,'0'+10
  1086.     ADD    AL,10
  1087.     JNC    @@2
  1088.     FIMUL    DCon10
  1089.     MOV    Temp,EAX
  1090.     FIADD    Temp
  1091.     INC    EDX
  1092.     JMP    @@1
  1093. @@2:    DEC    ESI
  1094.     RET
  1095.  
  1096. ; Get exponent
  1097. ; Out    EDX = Exponent (-4999..4999)
  1098.  
  1099. GetExponent:
  1100.  
  1101.     XOR    EAX,EAX
  1102.     XOR    EDX,EDX
  1103.     MOV    CL,[ESI]
  1104.     CMP    CL,'+'
  1105.     JE    @@1
  1106.     CMP    CL,'-'
  1107.     JNE    @@2
  1108. @@1:    INC    ESI
  1109. @@2:    MOV    AL,[ESI]
  1110.     SUB    AL,'0'+10
  1111.     ADD    AL,10
  1112.     JNC    @@3
  1113.     INC    ESI
  1114.     IMUL    EDX,10
  1115.     ADD    EDX,EAX
  1116.     CMP    EDX,500
  1117.     JB    @@2
  1118. @@3:    CMP    CL,'-'
  1119.     JNE    @@4
  1120.     NEG    EDX
  1121. @@4:    RET
  1122.  
  1123.     END
  1124.