home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / forth / compiler / fpc / source / sfloat2.seq < prev    next >
Text File  |  1990-02-11  |  38KB  |  1,128 lines

  1. \ SFLOAT2 - Second Module of Floating Point Extensions
  2. \
  3. \               (c) Copyright 1988 by Robert L. Smith
  4. \                       2300 St Francis Dr.
  5. \                       Palo Alto, CA 94303
  6. \                          (415)856-9321
  7. \
  8. \       Permission is granted to use this package or its derivatives for
  9. \       private use.  For permission to use it in programs or packages
  10. \       sold for profit, please contact the author.
  11. \
  12.  
  13. DEFINED NOFLOATING NIP #IF NOFLOATING #THEN
  14.  
  15. ANEW FLOGSRC
  16. \ LOADED,
  17. PREFIX
  18.  
  19. : FCONSTANT   ( F: r -- )  \ When creating an FCONSTANT
  20.               ( F: -- r )  \ When using a created FCONSTANT.
  21.         CREATE  FPOP , , ,
  22.         ;CODE
  23.         POP     BX
  24.         MOV     AX, 4 [BX]
  25.         MOV     CX, 2 [BX]
  26.         MOV     DX, 0 [BX]
  27.         MOV     BX, FSP
  28.         SUB     BX, # 6
  29.         MOV     FSP BX
  30.         MOV     4 [BX], AX
  31.         MOV     2 [BX], CX
  32.         MOV     0 [BX], DX
  33.         NEXT
  34.         END-CODE
  35.  
  36. : FVARIABLE   ( -- )       \ At creation time.
  37.               ( -- addr )  \ At run time.
  38.         VARIABLE  0 , 0 , ;
  39.  
  40. HEX
  41. DAA2 C90F 4001 FPUSH FCONSTANT PI
  42. 17F8 B172 3FFF FPUSH FCONSTANT FLN2
  43.          0 0 0 FPUSH FCONSTANT F0.0
  44.    0 8000 4000 FPUSH FCONSTANT F1.0
  45. D8A9 DE5B 3FFE FPUSH FCONSTANT FLOG10E          \ log base 10 of e = 1/ln(10)
  46. 8DDE 935D 4001 FPUSH FCONSTANT FLN10.0          \ log base e of 10
  47. 0000 A000 4003 FPUSH FCONSTANT F10.0
  48. 0000 8000 7FFF FPUSH FCONSTANT FINFINITY
  49. 0000 8000 3FFF FPUSH FCONSTANT F0.5
  50.  
  51. : F1.0+   ( F: r1 -- r2 )     F1.0 F+ ;
  52.  
  53. CODE F@   ( F: -- r ; addr -- )
  54.         POP     BX
  55.         MOV     AX, 4 [BX]
  56.         MOV     CX, 2 [BX]
  57.         MOV     DX, 0 [BX]
  58.         MOV     BX, FSP
  59.         SUB     BX, # 6
  60.         MOV     FSP BX
  61.         MOV     4 [BX], AX
  62.         MOV     2 [BX], CX
  63.         MOV     0 [BX], DX
  64.         NEXT
  65.         END-CODE
  66.  
  67. CODE F!   ( F: r -- ; addr -- )
  68.         MOV     BX, FSP
  69.         MOV     AX, 0 [BX]
  70.         MOV     CX, 2 [BX]
  71.         MOV     DX, 4 [BX]
  72.         ADD     BX, # 6
  73.         MOV     FSP BX
  74.         POP     BX
  75.         MOV     0 [BX], AX
  76.         MOV     2 [BX], CX
  77.         MOV     4 [BX], DX
  78.         NEXT
  79.         END-CODE
  80.  
  81. : F,   ( F: r -- )
  82.         HERE F#BYTES ALLOT F! ;
  83.  
  84. : 1/F   ( F: r1 -- r2 )
  85.         F1.0 FSWAP F/ ;
  86.  
  87. CODE FLOAT     ( F: -- r ; dbl -- )
  88.         CLEAR_LABELS
  89.         POP     AX
  90.         POP     BX
  91.         XOR     CX, CX
  92.         XOR     DX, DX
  93.         XOR     DI, DI
  94.         OR      AH, AH
  95.         JNS     2 $
  96.         OR      CH, # 80
  97.         NEG     AX
  98.         NEG     BX
  99.         SBB     AX, # 0
  100. 1 $:    SHR     AX
  101.         RCR     BX
  102.         RCR     DX
  103.         RCR     DI
  104.         INC     CX
  105. 2 $:    OR      BX, BX
  106.         JNE     1 $
  107.         OR      AX, AX
  108.         JNE     1 $
  109.         OR      CX, CX
  110.         JZ      3 $
  111.         ADD     CX, # 3FFF
  112. 3 $:    MOV     BX, FSP
  113.         SUB     BX, # 6
  114.         MOV     FSP BX
  115.         MOV     4 [BX], DI
  116.         MOV     2 [BX], DX
  117.         MOV     0 [BX], CX
  118.         NEXT
  119.         END-CODE
  120.  
  121. : IFLOAT   ( F: -- r ; n -- )   S>D FLOAT ;
  122.  
  123. CODE DINTABS   ( F: r -- ; -- dbl flag )  \ For Positive arguments.
  124.         CLEAR_LABELS                      \ Truncating.
  125.         MOV     BX, FSP
  126.         MOV     CX, 0 [BX]
  127.         MOV     AX, 2 [BX]
  128.         MOV     DI, 4 [BX]
  129.         ADD     BX, # 6
  130.         MOV     FSP BX
  131.         MOV     BX, DI
  132.         XOR     DI, DI          \ Make room for shifting in integer
  133.         XOR     DX, DX
  134.         OR      AX, AX
  135.         JNS     1 $             \ Test for zero (unnormalized number)
  136.         AND     CX, # 7FFF
  137.         SUB     CX, # 3FFF
  138.         JLE     1 $             \ Return zero if exponent is <= 0
  139.         CMP     CX, # 10
  140.         JGE     2 $
  141. 0 $:    SHL     AX, # 1         \ 0 < exponent < 16
  142.         RCL     DI, # 1
  143.         LOOP    0 $
  144. 1 $:    PUSH    DI
  145.         PUSH    DX
  146.         XOR     AX, AX          \ Send a flag of 0
  147.         PUSH    AX
  148.         NEXT
  149.  
  150. 2 $:    CMP     CX, # 20
  151.         JG      6 $
  152.         JE      7 $
  153.         SUB     CX, # 10        \ 16 <= exponent < 32.
  154.         JZ      5 $             \ Jump if exactly 16.
  155. 4 $:    SHL     BX, # 1         \ Else shift left.
  156.         RCL     AX, # 1
  157.         RCL     DI, # 1
  158.         LOOP    4 $
  159. 5 $:    PUSH    AX
  160.         PUSH    DI
  161.         XOR     AX, AX          \ Send a flag of zero.
  162.         PUSH    AX
  163.         NEXT
  164.  
  165. 6 $:    OR      CH, # 80        \ Overflow case.  Set ms bit of flag.
  166.         PUSH    DI
  167.         PUSH    AX
  168.         PUSH    CX
  169.         NEXT
  170.  
  171. 7 $:                            \ Result exactly fits 32 bits.
  172.         MOV     CX, # 7FFF      \ Flag is non-zero with ms bit off
  173.         PUSH    BX
  174.         PUSH    AX
  175.         PUSH    CX
  176.         NEXT
  177.  
  178.         END-CODE
  179.  
  180. WARNING @ WARNING OFF
  181.  
  182. : FIX   ( F: r -- ; -- d )
  183.         FDUP0<
  184.         IF    FABS F0.5 F+ DINTABS >R DNEGATE R>
  185.         ELSE  F0.5 F+ DINTABS
  186.         THEN 0<
  187.         IF     [ LAST @ NAME> ] LITERAL 2 FPERR
  188.         THEN ;
  189.  
  190. : INT    ( F: r -- ; -- d )
  191.         FDUP0<
  192.         IF    DINTABS DUP 0<
  193.               IF   [ LAST @ NAME> ] LITERAL 2 FPERR
  194.               ELSE
  195.                     IF   [ LAST @ NAME> ] LITERAL 2 FPERR
  196.                     THEN
  197.               THEN
  198.               DNEGATE
  199.         ELSE  DINTABS DUP
  200.               IF    [ LAST @ NAME> ] LITERAL 2 FPERR
  201.               ELSE  DROP
  202.               THEN
  203.         THEN ;
  204.  
  205. WARNING !
  206.  
  207. CODE TINTA   ( F: r -- ; -- lo mid hi )  \ Convert a floating number to
  208.         CLEAR_LABELS                    \ triple integer.
  209.         MOV     BX, FSP
  210.         MOV     CX, 0 [BX]
  211.         MOV     AX, 2 [BX]
  212.         MOV     DX, 4 [BX]
  213.         ADD     BX, # 6
  214.         MOV     FSP BX
  215.         XOR     BX, BX
  216.         XOR     DI, DI
  217.         AND     CX, # 7FFF      \ Knock off sign bit.
  218.         SUB     CX, # 3FFF      \ Un-bias the exponent
  219.         JLE     9 $
  220.         CMP     CX, # 10
  221.         JL      5 $
  222.         CMP     CX, # 20
  223.         JL      4 $
  224.         CMP     CX, # 30
  225.         JL      3 $
  226.         JG      7 $
  227.         MOV     DI, AX
  228.         MOV     BX, DX
  229.         XOR     AX, AX
  230.         SUB     CX, # 30
  231. 0 $:    JE      2 $
  232. 1 $:    SHL     DX, # 1
  233.         RCL     AX, # 1
  234.         RCL     BX, # 1
  235.         RCL     DI, # 1
  236.         LOOP    1 $
  237. 2 $:    PUSH    AX
  238.         PUSH    BX
  239.         PUSH    DI
  240.         NEXT
  241. 3 $:    MOV     BX, AX
  242.         MOV     AX, DX
  243.         XOR     DX, DX
  244.         SUB     CX, # 20
  245.         JMP     0 $
  246. 4 $:    SUB     CX, # 10
  247.         JMP     0 $
  248. 5 $:    MOV     DX, AX
  249.         XOR     AX, AX
  250.         OR      CX, CX
  251.         JMP     0 $
  252. 9 $:    XOR     AX, AX
  253.         JMP     2 $
  254.  
  255. 7 $:    OR      AH, AH          \ Test for unnormalized number (zero)
  256.         JNS     9 $
  257.         MOV     CX, # LAST @ NAME>
  258.         PUSH    CX
  259.         MOV     CX, # 2         \ Send overflow message
  260.         PUSH    CX
  261.         MOV     AX, # ' FPERR
  262.         JMP     AX
  263.         END-CODE
  264.  
  265. CODE FINT   ( F: r1 -- r2 )     \ Set true fractional bits to zero.
  266.         CLEAR_LABELS
  267.         MOV     BX, FSP         \ Get pointer to floating point stack.
  268.         MOV     DX, 2 [BX]
  269.         MOV     DI, # -1        \ Setup mask
  270.         MOV     AX, DI
  271.         OR      DH, DH
  272.         JNS     4 $             \ Jump if unnormalized (zero).
  273.         MOV     CX, 0 [BX]      \ Sign and exponent.
  274.         AND     CX, # 7FFF      \ Knock off sign.
  275.         SUB     CX, # 3FFF      \ Get unbiased exponent
  276.         JLE     4 $             \ Return zero if exponent <= 0.
  277.         CMP     CX, # 20        \ If exponent >= 20,
  278.         JGE     3 $             \ just leave.
  279.         CMP     CX, # 10
  280.         JL      1 $
  281.         XOR     AX, AX
  282.         SUB     CX, # 10
  283.         JZ      2 $
  284. 1 $:    SHR     AX, # 1         \ Shift in zeros from left.
  285.         RCR     DI, # 1
  286.         LOOP    1 $
  287. 2 $:    NOT     DI              \ Convert zeros to ones, and vice-versa.
  288.         NOT     AX
  289.         AND     4 [BX], DI
  290.         AND     2 [BX], AX
  291. 3 $:    NEXT
  292.  
  293. 4 $:    XOR     DX, DX
  294.         MOV     0 [BX], DX
  295.         MOV     2 [BX], DX
  296.         MOV     4 [BX], DX
  297.         NEXT
  298.         END-CODE
  299.  
  300. ALSO HIDDEN DEFINITIONS
  301.  
  302. LABEL RENORM            \ Normalize the number in (CX,AX,BX,DX)
  303.         CLEAR_LABELS
  304.         OR      AH, AH          \ Check if shift by bytes or words.
  305.         JZ      5 $             \ Branch if byte or word shift.
  306.         JNS     4 $             \ Branch if not already in place.
  307. 1 $:    ADD     DX, # 8000      \ Begin rounding process.
  308.         JZ      3 $             \ If result is zero, round to even.
  309.         ADC     BX, # 0
  310.         ADC     AX, # 0
  311.         JNC     2 $             \ Branch if no carry out.
  312.         RCR     AX, # 1         \ We generated a carry.  Shift it back.
  313.         RCR     BX, # 1
  314.         INC     CX              \ Modify the exponent to compensate.
  315. 2 $:    RET                     \ Return from subroutine.
  316.  
  317. 3 $:    AND     BL, # 0FE       \ Round to even case.
  318.         RET                     \ Return.
  319.  
  320. 4 $:    DEC     CX              \ Normalize step.  Decrement Exponent.
  321.         SHL     DX, # 1         \ Shift rest left by 1 bit.
  322.         RCL     BX, # 1
  323.         RCL     AX, # 1
  324.         JNO     4 $             \ Loop if no overflow (sign bit not set).
  325.         JMP     1 $             \ Finish by rounding.
  326.  
  327. 5 $:    OR      AX, AX          \ Can we shift by words?
  328.         JNZ     9 $             \ If not, jump.
  329.         OR      BX, BX          \ Can we shift by two words?
  330.         JNZ     7 $             \ If not, jump.
  331.         OR      DX, DX          \ Is fraction zero?
  332.         JNZ     6 $             \ If not, jump.
  333.         XOR     CX, CX          \ Make everything zero,
  334.         RET                     \ Then return.
  335.  
  336. 6 $:    MOV     AX, DX          \ Shift by two words.
  337.         SUB     CX, # 20        \ Decrement exponent by 32
  338.         JMP     8 $             \ Join rest of code.
  339.  
  340. 7 $:    MOV     AX, BX          \ Shift by one word.
  341.         MOV     BX, DX
  342.         SUB     CX, # 10        \ Subtract 16 from exponent.
  343. 8 $:    XOR     DX, DX          \ Clear least significant word.
  344.         OR      AH, AH          \ Can we shift by a byte?
  345.         JZ      9 $             \ Jump if we can shift by a byte.
  346.         JNS     4 $             \ If sign is not set, jump to normalize.
  347.         RET                     \ Otherwise, just return.
  348.  
  349. 9 $:    MOV     AH, AL          \ Shift left by one byte.
  350.         MOV     AL, BH
  351.         MOV     BH, BL
  352.         MOV     BL, DH
  353.         MOV     DH, DL
  354.         XOR     DL, DL
  355.         SUB     CX, # 8         \ Subtract 8 from exponent.
  356.         OR      AH, AH
  357.         JNS     4 $             \ If sign bit not set, go to Normalize.
  358.         RET                     \ Else just return.
  359.         END-CODE
  360.  
  361. : F**+N     ( F: r1 -- r2 ; n -- )
  362.         7FFF AND >R F1.0
  363.         BEGIN R@ 1 AND
  364.               IF   FOVER F*  THEN
  365.               R> 2/ DUP
  366.         WHILE >R FSWAP FDUP F* FSWAP
  367.         REPEAT
  368.         DROP FNIP ;
  369.  
  370. PREVIOUS DEFINITIONS
  371.  
  372. : F**N     ( F: r1 -- r2 ; n -- )  \ Floating number raised to integer power.
  373.         DUP 0<
  374.         IF    ABS [ ALSO HIDDEN ] F**+N F1.0 FSWAP F/
  375.         ELSE  F**+N
  376.         THEN ;
  377. PREVIOUS
  378.  
  379. : F**N*    ( F: r1 r2 -- r3 ; n -- )  \ Raise r2 to nth power and
  380.         [ ALSO HIDDEN ]
  381.         DUP 0<                        \ and multiply by r1.
  382.         IF      ABS F**+N F/
  383.         ELSE    F**+N F*
  384.         THEN ;
  385. PREVIOUS
  386.  
  387. DECIMAL
  388. CODE D2**N   ( n1 -- lo hi )
  389.         CLEAR_LABELS
  390.         POP     CX
  391.         XOR     AX, AX
  392.         XOR     BX, BX
  393.         CMP     CX, # 16
  394.         JAE     3 $
  395.         INC     BX
  396.         SHL     BX, CL
  397. 2 $:    PUSH    BX
  398.         PUSH    AX
  399.         NEXT
  400. 3 $:    CMP     CX, # 32
  401.         JAE     2 $
  402.         SUB     CX, # 16
  403.         INC     AX
  404.         SHL     AX, CL
  405.         PUSH    BX
  406.         PUSH    AX
  407.         NEXT
  408.         END-CODE
  409.  
  410. DECIMAL
  411. HEX
  412.  
  413. \ Floating division with partial remainder.
  414. \    The division routine that follows is based on the work of Roedy Green,
  415. \    the author of BBL/Abundance.
  416.  
  417. CODE F/PREM     ( F: r1 r2 -- urrem urquot )  \ Results are unnormalized.
  418.         CLEAR_LABELS
  419.         MOV     BX, FSP         \ Floating Point Stack Pointer to BX
  420.         MOV     DI, 2 [BX]      \ FDHi  High part of Denominator fraction
  421.         OR      DI, DI          \ Check for unnormalized (zero) divisor.
  422.         JNS     1 $             \ Branch to Divide by zero routine.
  423.         PUSH    SI              \ Save SI, BP, and DS
  424.         PUSH    BP
  425.         PUSH    DS
  426.         MOV     DX, 8 [BX]      \ FNHi  High part of Numerator
  427.         OR      DH, DH          \ Check for unnormalized numerator.
  428.         JNS     2 $             \ Branch to zero case, if unnormalized.
  429.         MOV     CX, 6 [BX]      \ SXN   Sign + Exponent of Numerator
  430.         MOV     AX, 0 [BX]      \ SXD   Sign + Exponent of Denominator
  431.         MOV     SI, CX
  432.         AND     SI, # 7FFF      \ XN
  433.         CMP     SI, # 20
  434.         JLE     2 $             \ Treat small numerator as zero.
  435.         MOV     BP, AX
  436.         AND     BP, # 7FFF      \ XD
  437.         SUB     SI, BP          \ XN - XD
  438.         JS      3 $             \ Jump if XN < XD
  439.         CMP     SI, # 20
  440.         JL      8 $             \ Jump if  0 <= (XN-XD) < 32
  441.         SUB     CX, # 20        \ SXN - 32 -> SXR
  442.         MOV     BP, AX          \ SXD
  443.         XOR     BP, CX
  444.         AND     BP, # 8000      \ SQ
  445.         ADD     SI, # 3FFF      \ Make biased XQ
  446.         JS      4 $             \ If sign is set, its an OVERFLOW condition.
  447.         OR      SI, BP          \ SXQ
  448.         MOV     AX, 0A [BX]     \ FN1  ( Initially the low part )
  449.         CMP     DX, DI          \ Compare FNHi with FDHi
  450.         JA      7 $
  451.         JE      6 $
  452. 0 $:    MOV     0 [BX], SI      \ Save biased SXQ
  453.         MOV     6 [BX], CX      \ SXR
  454.         MOV     BP, 4 [BX]      \ FDLo  Low part of Denominator fraction
  455.         XOR     BX, BX
  456.         XOR     CX, CX
  457.         JMP     1E $
  458.  
  459. 1 $:    JMP     L$              \ Jump to 1C $
  460.  
  461. 2 $:    XOR     AX, AX          \ Set results to zero.
  462.         POP     DS
  463.         POP     BP
  464.         POP     SI
  465.         MOV     0A [BX], AX
  466.         MOV     8 [BX], AX
  467.         MOV     6 [BX], AX
  468.         MOV     4 [BX], AX
  469.         MOV     2 [BX], AX
  470.         MOV     WORD 0 [BX], # 401F
  471.         NEXT
  472.  
  473. 3 $:                            \ Exponent of num < exponent of denominator.
  474.         XOR     AX, AX          \ Set quotient to 0
  475. \                               \ Remainder is Numerator
  476.         MOV     4 [BX], AX      \ Quotient is 0
  477.         MOV     2 [BX], AX
  478.         MOV     WORD 0 [BX], # 401F     \ With quotient exponent of 401F
  479.         POP     DS              \ Restore registers.
  480.         POP     BP
  481.         POP     SI
  482.         NEXT
  483.  
  484. 4 $:    JMP     L$              \ Jump to 1A $
  485. 6 $:    CMP     AX, BX          \ FNHi = FDHi.  Compare FNLo with FDLo.
  486.         JB      0 $
  487. 7 $:                            \ XN >= XD + 32, and FN >= FD
  488.         INC     CX
  489.         INC     SI              \ Overflow?
  490.         JO      4 $
  491.         MOV     0 [BX], SI      \ SXQ
  492.         MOV     6 [BX], CX      \ SXR
  493.         MOV     BP, 4 [BX]      \ FDLo
  494.         XOR     BX, BX
  495.         XOR     CX, CX
  496.         SHR     DX, # 1
  497.         RCR     AX, # 1
  498.         RCR     BX, # 1
  499. 1E $:   JMP     0E $
  500.  
  501. 8 $:                            \ 0 <= (XN - XD) < 32
  502.         AND     CX, # 8000      \ SN
  503.         OR      BP, CX          \ SN + XD -> SXR
  504.         AND     AX, # 8000
  505.         XOR     CX, AX          \ SQ
  506.         OR      CX, # 401F      \ SXQ  The exponent is 32
  507.         MOV     0 [BX], CX      \ SXQ
  508.         MOV     6 [BX], BP      \ SXR
  509.         MOV     BP, 4 [BX]      \ FDLo  Low part of Denominator fraction
  510.         MOV     AX, 0A [BX]     \ FNLo  Low part of Numerator fraction
  511. \ Numerator is in (DX, AX, BX, CX).  Denominator is in (DI, BP)
  512.         MOV     CX, AX          \ Preliminary shift right by 32
  513.         MOV     BX, DX
  514.         XOR     AX, AX          \ Clear MS parts of numerator
  515.         MOV     DX, AX
  516.         CMP     SI, # 10        \ Test shift count
  517.         JL      0B $
  518.         MOV     AX, BX          \ Shift left by 16
  519.         MOV     BX, CX
  520.         XOR     CX, CX
  521.         SUB     SI, # 10
  522.         JZ      0E $
  523. 0B $:   CMP     SI, # 8
  524.         JL      0C $
  525.         MOV     DL, AH          \ Shift left by 8
  526.         MOV     AH, AL
  527.         MOV     AL, BH
  528.         MOV     BH, BL
  529.         MOV     BL, CH
  530.         MOV     CH, CL
  531.         XOR     CL, CL
  532.         SUB     SI, # 8
  533.         JZ      0E $
  534. 0C $:   OR      SI, SI          \ Test for zero exponent difference.
  535.         JZ      0E $
  536.         XCHG    CX, SI          \ Restore count and FN3
  537. 0D $:   SHL     SI, # 1         \ Shift left by specified count
  538.         RCL     BX, # 1
  539.         RCL     AX, # 1
  540.         RCL     DX, # 1
  541.         LOOP    0D $
  542.         MOV     CX, SI
  543. 0E $:   MOV     DS, CX          \ Move FN3 out of the way for a while.
  544.         CMP     DX, DI          \ See if trial divide would overflow
  545.         JB      0F $            \ Jump if not.
  546.         MOV     SI, # -1        \ Guess initial quotient is  FFFF
  547.         MOV     CX, AX          \ FN1
  548.         SUB     CX, BP          \ FN1 - FDLo
  549.         MOV     BX, BP          \ FN2 + FDLo  ( FN2 = 0 )
  550.         ADD     CX, DI          \ FDHi + (FN1 - FDLo)
  551.         JC      11 $            \ Carry means result is OK
  552.         JMP     10 $            \ No Carry means we have to modify remainder.
  553.  
  554. 0F $:   DIV     DI              \ Initial approximation. Divide by FDHi
  555.         MOV     SI, AX          \ Save initial quotient estimate = g0
  556.         MOV     CX, DX          \ Save r0
  557.         MUL     BP              \ Correction factor = g0 * FDLo
  558.         SUB     BX, AX
  559.         SBB     CX, DX          \ r1 = (s * r0) + FN2 - (g0 * FDLo)
  560.         JNC     11 $            \ Jump if r1 >= 0   (no borrow)
  561. 10 $:   DEC     SI              \ Decrement g by 1, at least.
  562.         ADD     BX, BP          \ r2 = r1 + FD
  563.         ADC     CX, DI
  564.         JC      11 $            \ Jump if r2 >= 0
  565.         DEC     SI              \ Decrement g by 1 for last time.
  566.         ADD     BX, BP
  567.         ADC     CX, DI          \ r3 = r2 + den
  568. 11 $:   MOV     AX, BX
  569.         MOV     DX, CX
  570.         MOV     BX, DS          \ FN3
  571.         MOV     DS, SI          \ MS part of Quotient
  572.         CMP     DX, DI
  573.         JAE     14 $
  574.         DIV     DI              \ Approximate LS part of quotient.
  575.         MOV     SI, AX
  576.         MOV     CX, DX
  577.         MUL     BP              \ Correction factor
  578.         SUB     BX, AX
  579.         SBB     CX, DX          \ r5 = s*r4 + FN3 - g1*FDLo
  580.         JNC     13 $            \ Jump if no borrow
  581. 12 $:   DEC     SI              \ Decrement g1 by 1
  582.         ADD     BX, BP          \ Add denominator back in to remainder
  583.         ADC     CX, DI
  584.         JC      13 $            \ Jump if no carry
  585.         DEC     SI              \ Decrement g1 again
  586.         ADD     BX, BP          \ Add denominator again
  587.         ADC     CX, DI
  588. 13 $:
  589.         MOV     BP, BX          \ Make room for FSP
  590.         MOV     AX, DS
  591.         POP     DS              \ Restore DS
  592.         MOV     BX, FSP
  593.         MOV     0A [BX], BP     \ LS part of Remainder
  594.         MOV     8 [BX], CX      \ MS part of Remainder
  595.         MOV     4 [BX], SI      \ LS part of Quotient
  596.         MOV     2 [BX], AX      \ MS part of Quotient
  597.         POP     BP              \ Restore BP
  598.         POP     SI              \ Restore SI
  599.         NEXT
  600.  
  601. 14 $:   MOV     SI, # FFFF      \ MS num = MS den.  Start with trial g0 = s-1
  602.         MOV     CX, AX
  603.         SUB     CX, BP          \ midnum - lsden
  604.         ADD     BX, BP
  605.         ADD     CX, DI          \ msnum + (midnum-lsnum)
  606.         JC      13 $            \ Good quotient if Carry is set
  607.         JMP     12 $            \ Otherwise, correct result
  608.  
  609. 1A $: L$:                       \ Overflow case.  Let Rem = Num.
  610.         MOV     AX, # -1
  611.         OR      BP, # 7FFF      \ Set quotient to maximum, with SQ.
  612.         MOV     DX, # 2         \ Indicate Overflow to error routine.
  613.         POP     DS
  614.         MOV     0A [BX], AX
  615.         MOV     8 [BX], AX
  616.         MOV     6 [BX], BP
  617.         POP     BP
  618.         POP     SI
  619. 1B $:   MOV     BX, # LAST @ NAME>
  620.         PUSH    BX
  621.         PUSH    DX
  622.         MOV     AX, # ' FPERR
  623.         JMP     AX
  624.  
  625. 1C $: L$:                       \ Divide by zero case.
  626.         MOV     DI, # -1        \ Set exponent bits to 1.
  627.         XOR     AX, AX          \ Clear rest of quotient.
  628. \                               \ Set remainder to numerator!
  629.         MOV     DX, # 1         \ Set indicator to Overflow.
  630.         MOV     4 [BX], AX      \ Clear fractional part of quotient,
  631.         MOV     2 [BX], AX
  632.         MOV     0 [BX], DI      \ But set exponent bits to 1
  633.         JMP     1B $            \ Jump to common error code.
  634.  
  635.         END-CODE
  636.  
  637. ALSO HIDDEN DEFINITIONS
  638.  
  639. CREATE LOGTAB1          \ Table of logarithms for argument > 1
  640.         0000 , 0000 , 0000 ,   0FC1 , 4D87 , 3C1A ,   1F0A , 30C0 , 1163 ,
  641.         2DE1 , A515 , CAD7 ,   3C4E , 0EDC , 55E6 ,   4A55 , 4BE0 , 7FD5 ,
  642.         57FC , C1C2 , 9E4F ,   6549 , 6A73 , D15B ,   723F , DF1E , 6A69 ,
  643.         7EE4 , 61B5 , 78F9 ,   8B3A , E55D , 5D30 ,   9747 , 15D7 , 88EA ,
  644.         A30C , 5E10 , E2F6 ,   AE8D , EDFA , C04E ,   B9CE , BFB5 , DE80 ,
  645.         C4D1 , 9C36 , 0A13 ,   CF99 , 1F65 , FCC2 ,   DA27 , BBDE , 647B ,
  646.         E47F , BE3C , D4D1 ,
  647.  
  648. CREATE LOGTAB2          \ Table of logarithms for argument < 1
  649.         0000 , 0000 , 0000 ,   2082 , BB13 , CE89 ,   4216 , 62D6 , 78E8 ,
  650.         64CD , 7975 , 6526 ,   88BC , 7411 , 1F24 ,   ADFA , 035A , A1EE ,
  651.         D49F , 69E4 , 56CF ,   FCC8 , E365 , 9D9C ,
  652.  
  653. LABEL FLN+          \ Fractional part treated as if 1.0 <= X < 1.5625
  654.                     \ DI = Unbiased Exponent, DX = MS fract., AX = LS fract.
  655.                     \ SI and BP have been pushed to stack.
  656.         CLEAR_LABELS
  657.         DEC     DI              \ Decrement the true exponent,
  658.         PUSH    DI              \ Save it for the time being.
  659.         MOV     DI, DX
  660.         AND     DI, # FC00      \ Create a divisor of MS 6 bits of argument.
  661.         MOV     CL, DH          \ Shift left by 6 = 8-2.  First by bytes.
  662.         MOV     DH, DL
  663.         MOV     DL, AH
  664.         MOV     AH, AL
  665.         XOR     AL, AL
  666.         AND     CX, # 7F        \ Discard MS bit by masking.
  667.         SHR     CX, # 1         \ Now shift right by 2 positions.
  668.         RCR     DX, # 1
  669.         RCR     AX, # 1
  670.         SHR     CX, # 1
  671.         RCR     DX, # 1
  672.         RCR     AX, # 1
  673.         PUSH    CX              \ Save Index value.
  674.         OR      CX, CX          \ Delete these 5 instructions if you have
  675.         JNZ     0 $             \ an NEC V-20 chip or equivalent.
  676.         MOV     BX, DX
  677.         JMP     10 $
  678.  
  679. 0 $:    SHR     DX, # 1         \ Shift fractional part right by 1
  680.         RCR     AX, # 1         \   so that division won't overflow.
  681.         DIV     DI              \ Divide by MS 6 bits of original fraction.
  682.         MOV     BX, AX          \ Save MS part of quotient in BX.
  683.         XOR     AX, AX
  684.         DIV     DI              \ Generate LS part of quotient.
  685.         SHR     DI, # 1         \ Test for rounding.
  686.         CMP     DX, DI
  687.         CMC
  688.         ADC     AX, # 0
  689.         ADC     BX, # 0
  690. 10 $:   MOV     CX, AX          \ LS part of quotient to CX.
  691.         MOV     DL, BH
  692.         XOR     DH, DH
  693.         SHL     DX, # 1
  694.         SHL     DX, # 1         \ y*2^-6
  695.         MOV     AX, # AAAB
  696.         SUB     AX, DX          \ 2/3 - y*2^-6
  697.         MUL     BX              \ *y
  698.         SHR     DX, # 1
  699.         SHR     DX, # 1
  700.         SHR     DX, # 1
  701.         SHR     DX, # 1
  702.         SHR     DX, # 1         \ *(2^-5)
  703.         ADC     DX, # 0         \ Round
  704.         MOV     DI, DX          \ temp to DI
  705.         MOV     AX, BX          \ y
  706.         MUL     BX              \ y^2
  707.         MOV     BP, DX          \ (yhi^2)hi
  708.         MOV     SI, AX          \ (yhi^2)lo
  709.         MOV     AX, # CCCD
  710.         SUB     AX, DI          \ (4/5) - temp
  711.         MUL     BP              \ * y^2
  712.         MOV     DI, DX          \ temp2
  713.         MOV     AX, BX
  714.         MUL     CX              \ yhi*ylo
  715.         SHL     AX, # 1         \ 2*yhi*ylo
  716.         RCL     DX, # 1
  717.         ADC     BP, # 0
  718.         ADD     SI, DX          \ (y^2)lo
  719.         ADC     BP, # 0         \ (y^2)hi
  720.         SHR     DI, # 1
  721.         SHR     DI, # 1
  722.         SHR     DI, # 1
  723.         SHR     DI, # 1
  724.         SHR     DI, # 1         \ * (2^-5)
  725.         ADC     DI, # 0
  726.         MOV     AX, BX
  727.         SUB     AX, DI          \ y - (y^2)*(2^-5)*(4/5) + stuff
  728.         PUSH    CX              \ ylo
  729.         PUSH    BX              \ yhi
  730.         XOR     CX, CX
  731.         MOV     CH, AL
  732.         MOV     AL, AH
  733.         XOR     AH, AH
  734.         SHL     CX, # 1
  735.         RCL     AX, # 1
  736.         SHL     CX, # 1
  737.         RCL     AX, # 1         \ *(2^-6) in Double precision
  738.         MOV     BX, # AAAA
  739.         MOV     DI, # AAAB
  740.         SUB     DI, CX
  741.         SBB     BX, AX          \ (2/3) - (2^-6)*(y - stuff) in (BX,DI).
  742.         MOV     AX, BX
  743.         MUL     BP              \ BP = y^2 hi
  744.         MOV     CX, AX
  745.         MOV     AX, DI
  746.         MOV     DI, DX
  747.         MUL     BP
  748.         ADD     CX, DX
  749.         ADC     DI, # 0
  750.         MOV     AX, BX
  751.         MUL     SI
  752.         ADD     CX, DX
  753.         ADC     DI, # 0         \ * y^2 dbl.  in (DI,CX)
  754.         POP     BX              \ yhi
  755.         POP     DX              \ ylo
  756.         PUSH    SI
  757.         PUSH    BP
  758.         MOV     SI, DX          \ y in (BX,SI)
  759.         MOV     AX, DI
  760.         MUL     BX
  761.         XCHG    AX, CX
  762.         MOV     BP, DX
  763.         MUL     BX
  764.         ADD     CX, DX
  765.         ADC     BP, # 0
  766.         MOV     AX, SI
  767.         MUL     DI
  768.         ADD     CX, DX
  769.         ADC     BP, # 0         \ * y
  770.         SHR     BP, # 1
  771.         RCR     CX, # 1
  772.         SHR     BP, # 1
  773.         RCR     CX, # 1
  774.         SHR     BP, # 1
  775.         RCR     CX, # 1
  776.         SHR     BP, # 1
  777.         RCR     CX, # 1
  778.         SHR     BP, # 1
  779.         RCR     CX, # 1         \ * (2^-5)  in (BP,CX)
  780.         ADC     CX, # 0
  781.         ADC     BP, # 0         \ Round.
  782.         POP     AX              \ y^2 hi
  783.         POP     DX              \ y^2 lo
  784.         SUB     DX, CX
  785.         SBB     AX, BP          \ y^2 - stuff  in (AX,DX)
  786.         SHR     AX, # 1
  787.         RCR     DX, # 1
  788.         SHR     AX, # 1
  789.         RCR     DX, # 1
  790.         SHR     AX, # 1
  791.         RCR     DX, # 1
  792.         SHR     AX, # 1
  793.         RCR     DX, # 1
  794.         SHR     AX, # 1
  795.         RCR     DX, # 1
  796.         SHR     AX, # 1
  797.         RCR     DX, # 1         \ * (2^-6)
  798.         SUB     SI, DX
  799.         SBB     BX, AX
  800.         MOV     DX, BX          \ Result now in (DX,SI), unnormalized.
  801.         XOR     AX, AX
  802.         SHR     DX, # 1
  803.         RCR     SI, # 1
  804.         RCR     AX, # 1
  805.         SHR     DX, # 1
  806.         RCR     SI, # 1
  807.         RCR     AX, # 1
  808.         SHR     DX, # 1
  809.         RCR     SI, # 1
  810.         RCR     AX, # 1
  811.         SHR     DX, # 1
  812.         RCR     SI, # 1
  813.         RCR     AX, # 1         \ * (2^-4)  Binary point 1 place to left.
  814.         POP     BX              \ Get table index.
  815.         SHL     BX, # 1
  816.         MOV     DI, BX
  817.         SHL     BX, # 1
  818.         ADD     BX, DI          \ Index * 6
  819.         ADD     BX, # LOGTAB1   \ Add base to offset
  820.         ADD     AX, 4 [BX]      \ Add table value to logarithm
  821.         ADC     SI, 2 [BX]
  822.         ADC     DX, 0 [BX]
  823.         XCHG    AX, DX          \ Rearrange registers for normalizing.
  824.         MOV     BX, SI
  825.         MOV     CX, # 3FFE      \ Put in an exponent (-1, biased)
  826. 1 $:    CALL    RENORM
  827.         MOV     BP, BX
  828.         MOV     BX, FSP
  829.         MOV     4 [BX], BP      \ Push partial logarithm
  830.         MOV     2 [BX], AX
  831.         MOV     0 [BX], CX
  832.         XCHG    BP, BX
  833.         POP     DI              \ Unbiased exponent.
  834.         MOV     CX, # 400F      \ Starting exponent for I*ln(2)
  835.         OR      DI, DI
  836.         JNS     2 $
  837.         OR      CH, # 80
  838.         NEG     DI
  839. 2 $:    MOV     AX, DI
  840.         MOV     DX, # 17F8      \ Lo part of ln(2)
  841.         MUL     DX
  842.         MOV     BX, DX          \ BX = middle part
  843.         XCHG    AX, DI          \ DI = lowest part
  844.         MOV     DX, # B172      \ Hi part of ln(2)
  845.         MUL     DX
  846.         ADD     BX, AX          \ Final middle part
  847.         ADC     DX, # 0         \ Possible carry to high part
  848.         MOV     AX, DX          \ High part to AX
  849.         MOV     DX, DI          \ Lo part to DX.  Index*ln(2) = (AX,BX,DX)
  850.         CALL    RENORM
  851.         XCHG    BX, BP
  852.         SUB     BX, # 6
  853.         MOV     FSP BX
  854.         MOV     4 [BX], BP
  855.         MOV     2 [BX], AX
  856.         MOV     0 [BX], CX
  857.         POP     BP              \ Restore BP
  858.         POP     SI              \ Restore SI
  859.         JMP     ' F+            \ Add to basic logarithm.
  860.         END-CODE
  861.  
  862. PREVIOUS DEFINITIONS ALSO HIDDEN
  863.  
  864. CODE FLN   ( F: r1 -- r2 )   \ Natural logarithm function.   Time: 1260 usec.
  865.         MOV     BX, FSP
  866.         MOV     DI, 0 [BX]      \ Sign and biased exponent.
  867.         MOV     DX, 2 [BX]      \ MS part of fraction.
  868.         MOV     AX, 4 [BX]      \ LS part of fraction.
  869.         OR      DI, DI
  870.         JS      4 $
  871.         OR      DX, DX
  872.         JS      5 $
  873.         MOV     CX, # 8         \ Zero argument for FLN
  874. 3 $:    MOV     DX, # LAST @ NAME>
  875.         PUSH    DX
  876.         PUSH    CX
  877.         MOV     AX, # -1        \ Set result to largest negative number.
  878.         MOV     4 [BX], AX
  879.         MOV     2 [BX], AX
  880.         MOV     0 [BX], AX
  881.         MOV     AX, # ' FPERR
  882.         JMP     AX
  883.  
  884. 4 $:    MOV     CX, # 4         \ Negative argument for FLN
  885.         JMP     3 $
  886.  
  887. 5 $:    PUSH    SI              \ Save SI and BP
  888.         PUSH    BP
  889.         SUB     DI, # 3FFF      \ Unbiased exponent.
  890.         CMP     DX, # C800      \ MS part of fraction.
  891.         JAE     6 $
  892.         JMP     FLN+            \ Jump if in range 1.0 to 1.5625
  893.  
  894. 6 $:    PUSH    DI              \ Save true exponent.
  895.         MOV     DI, DX
  896.         NEG     DX
  897.         NEG     AX
  898.         SBB     DX, # 0         \ Negated argument  ( 1 - arg )
  899.         XOR     CX, CX
  900.         SHL     AX, # 1         \ Shift argument left by 5.
  901.         RCL     DX, # 1
  902.         RCL     CX, # 1
  903.         SHL     AX, # 1
  904.         RCL     DX, # 1
  905.         RCL     CX, # 1
  906.         SHL     AX, # 1
  907.         RCL     DX, # 1
  908.         RCL     CX, # 1
  909.         SHL     AX, # 1
  910.         RCL     DX, # 1
  911.         RCL     CX, # 1
  912.         SHL     DX, # 1         \ Yes - I do mean this instruction!
  913.         RCL     CX, # 1         \ Finished shift.
  914.         PUSH    CX              \ Save Index value.
  915.         SHR     DX, # 1         \ Shift right by 1.
  916.         MOV     BX, DX          \ This instruction and next may save a JMP !
  917.         MOV     CX, AX
  918.         AND     DI, # F800
  919.         ADD     DI, # 0800
  920.         JZ      7 $             \ Test for zero divisor (really 1.0).
  921.         DIV     DI              \ Create y = (x/div)*(2^4)
  922.         MOV     BX, AX          \ Save MS part of quotient in BX
  923.         XOR     AX, AX
  924.         DIV     DI
  925.         MOV     CX, AX          \ LS part of quotient.
  926. 7 $:    MOV     AX, BX
  927.         SHR     AX, # 1
  928.         SHR     AX, # 1
  929.         SHR     AX, # 1
  930.         SHR     AX, # 1
  931.         SHR     AX, # 1         \ y*(2^-5)
  932.         ADD     AX, # AAAB      \ + (2/3)
  933.         MUL     BX              \ * y
  934.         SHR     DX, # 1
  935.         SHR     DX, # 1
  936.         SHR     DX, # 1
  937.         SHR     DX, # 1         \ * (2^-4)
  938.         ADC     DX, # 0         \ Round
  939.         ADD     DX, # CCCD      \ + (4/5)
  940.         MOV     DI, DX          \ temp to DI
  941.         MOV     AX, BX          \ y
  942.         MUL     BX              \ yhi^2
  943.         MOV     BP, DX          \ (yhi^2)hi
  944.         MOV     SI, AX          \ (yhi^2)lo
  945.         MOV     AX, DX
  946.         MUL     DI              \ temp * y^2
  947.         SHL     AX, # 1
  948.         ADC     DX, # 0         \ Round DX
  949.         MOV     DI, DX          \ temp2
  950.         MOV     AX, BX
  951.         MUL     CX              \ yhi*ylo
  952.         SHL     AX, # 1         \ 2*yhi*ylo
  953.         RCL     DX, # 1
  954.         ADC     BP, # 0
  955.         ADD     SI, DX          \ (y^2)lo
  956.         ADC     BP, # 0         \ (y^2)hi
  957.         XOR     DX, DX
  958.         SHR     DI, # 1
  959.         RCR     DX, # 1
  960.         SHR     DI, # 1
  961.         RCR     DX, # 1
  962.         SHR     DI, # 1
  963.         RCR     DX, # 1
  964.         SHR     DI, # 1
  965.         RCR     DX, # 1         \ * (2^-4) double
  966.         ADD     DX, CX
  967.         ADC     DI, BX          \ + ydbl
  968.         SHR     DI, # 1
  969.         RCR     DX, # 1
  970.         SHR     DI, # 1
  971.         RCR     DX, # 1
  972.         SHR     DI, # 1
  973.         RCR     DX, # 1
  974.         SHR     DI, # 1
  975.         RCR     DX, # 1
  976.         SHR     DI, # 1
  977.         RCR     DX, # 1         \ * (2^-5) double
  978.         ADD     DX, # AAAB      \           templo
  979.         ADC     DI, # AAAA      \ + (2/3)   temphi
  980.         PUSH    SI
  981.         MOV     AX, BX          \ yhi = A
  982.         MUL     DX              \ A*D
  983.         MOV     SI, DX          \ ADhi
  984.         MOV     AX, CX          \ B
  985.         MUL     DI              \ B*C
  986.         ADD     SI, DX          \ ADhi + BChi , no carry out.
  987.         MOV     AX, BX          \ A
  988.         MUL     DI              \ A*C
  989.         ADD     SI, AX          \ AClo + ADhi + BChi
  990.         ADC     DX, # 0         \ AChi + cy
  991.         MOV     DI, DX          \ new temphi = new C
  992.         MOV     AX, SI          \ new D
  993.         MUL     BP              \ A*D
  994.         POP     SI              \ y^2lo = B
  995.         PUSH    CX              \ ylo
  996.         MOV     CX, DX          \ ADhi
  997.         MOV     AX, DI          \ C
  998.         MUL     SI              \ B*C
  999.         ADD     CX, DX          \ ADhi + BChi , no carry out.
  1000.         MOV     AX, BP          \ A
  1001.         MUL     DI              \ A*C
  1002.         ADD     CX, AX          \ AClo + ADhi + BChi
  1003.         ADC     DX, # 0         \ AChi
  1004.         SHR     DX, # 1
  1005.         RCR     CX, # 1
  1006.         SHR     DX, # 1
  1007.         RCR     CX, # 1
  1008.         SHR     DX, # 1
  1009.         RCR     CX, # 1
  1010.         SHR     DX, # 1
  1011.         RCR     CX, # 1         \ * (2^-4)
  1012.         ADC     CX, # 0
  1013.         ADC     DX, # 0         \ Round
  1014.         ADD     SI, CX
  1015.         ADC     BP, DX          \ + y^2
  1016.         XOR     DX, DX
  1017.         SHR     BP, # 1
  1018.         RCR     SI, # 1
  1019.         RCR     DX, # 1
  1020.         SHR     BP, # 1
  1021.         RCR     SI, # 1
  1022.         RCR     DX, # 1
  1023.         SHR     BP, # 1
  1024.         RCR     SI, # 1
  1025.         RCR     DX, # 1
  1026.         SHR     BP, # 1
  1027.         RCR     SI, # 1
  1028.         RCR     DX, # 1
  1029.         SHR     BP, # 1
  1030.         RCR     SI, # 1
  1031.         RCR     DX, # 1         \ * (2^-5)
  1032.         POP     CX              \ ylo
  1033.         ADD     CX, SI
  1034.         ADC     BX, BP          \ Result in (BX,CX)
  1035.         SHR     BX, # 1
  1036.         RCR     CX, # 1
  1037.         RCR     DX, # 1
  1038.         SHR     BX, # 1
  1039.         RCR     CX, # 1
  1040.         RCR     DX, # 1         \ * (2^-2)
  1041.         MOV     AX, BX
  1042.         POP     BX              \ Index
  1043.         SHL     BX
  1044.         MOV     DI, BX
  1045.         SHL     DI
  1046.         ADD     BX, DI
  1047.         JZ      8 $
  1048.         ADD     BX, # LOGTAB2
  1049.         ADD     DX, 4 [BX]
  1050.         ADC     CX, 2 [BX]
  1051.         ADC     AX, 0 [BX]      \ Add in logarithm from table
  1052. 8 $:    MOV     BX, CX
  1053.         MOV     CX, # BFFD      \ -1*(2^-2) to biased exponent.
  1054.         JMP     1 $             \ Jump to common code
  1055.         END-CODE
  1056.  
  1057. \ End of Logarithm Function.
  1058.  
  1059. PREVIOUS DEFINITIONS
  1060.  
  1061. : FLOG     ( F: r1 -- r2 )
  1062.         FLN FLOG10E F* ;
  1063. HEX
  1064.  
  1065. CODE F/LN2     ( F: r -- r/ln2 )    \ Divide by natural log of 2
  1066.         CLEAR_LABELS
  1067.         MOV     BX, FSP
  1068.         MOV     DX, 2 [BX]
  1069.         OR      DH, DH
  1070.         JNS     4 $             \ Check for zero.
  1071.         MOV     CX, 0 [BX]
  1072.         MOV     DI, 4 [BX]
  1073.         MOV     BX, DX
  1074.         PUSH    SI
  1075.         PUSH    BP
  1076.         INC     CX
  1077.         MOV     AX, DI          \ flo = B
  1078.         MOV     DX, # 0B8AA     \ (1/ln2 )hi = C
  1079.         MUL     DX
  1080.         MOV     SI, DX          \ BCh
  1081.         MOV     BP, AX          \ BCl
  1082.         MOV     AX, BX          \ fhi = A
  1083.         MOV     DX, # 03B29     \ (1/ln2)lo = D
  1084.         MUL     DX
  1085.         ADD     BP, AX          \ ADl + BCl
  1086.         ADC     SI, DX          \ ADh + BCh
  1087.         MOV     AX, DI          \ B
  1088.         MOV     DX, # 03B29     \ D
  1089.         MUL     DX
  1090.         ADD     BP, DX          \ BDh + ADl + BCl
  1091.         ADC     SI, # 0         \ ADh + BCh + cy
  1092.         MOV     AX, BX          \ A
  1093.         MOV     DX, # 0B8AA     \ C
  1094.         MUL     DX
  1095.         ADD     AX, SI          \ Prod low
  1096.         ADC     DX, # 0         \ Prod high
  1097.         JS      1 $             \ Br if ms bit set
  1098.         SHL     BP, # 1         \ Else normalize
  1099.         RCL     AX, # 1
  1100.         RCL     DX, # 1
  1101.         DEC     CX
  1102. 1 $:    ADD     BP, # 08000     \ Round
  1103.         ADC     AX, # 0
  1104.         ADC     DX, # 0
  1105.         JC      3 $
  1106. 2 $:    POP     BP              \ Restore
  1107.         POP     SI
  1108.         MOV     BX, FSP
  1109.         MOV     4 [BX], AX      \ Push results
  1110.         MOV     2 [BX], DX
  1111.         MOV     0 [BX], CX
  1112.         NEXT
  1113.  
  1114. 3 $:    RCR     DX, # 1         \ Rare case of renorm on rounding
  1115.         RCR     AX, # 1
  1116.         INC     CX
  1117.         JMP     2 $
  1118.  
  1119. 4 $:    XOR     AX, AX          \ Zero argument case.
  1120.         MOV     4 [BX], AX
  1121.         MOV     2 [BX], AX
  1122.         MOV     0 [BX], AX
  1123.         NEXT
  1124.         END-CODE
  1125.  
  1126. \ End of F/LN2
  1127.  
  1128.