home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG032.ARK / TBASICA2.ASM < prev    next >
Assembly Source File  |  1984-04-29  |  47KB  |  1,912 lines

  1. * RTN. B.11
  2. * FIXED POINT MULTIPLY
  3. * (HL) TIMES (DE), PRODUCT IN WORK1
  4. FMUL    PUSH    D    ;SAVE REGISTERS
  5.     PUSH    H
  6.     XCHG
  7.     LXI    D,TEMP2    ;MOVE OPERANDS INTO TEMP1 AND TEMP2
  8.     LXI    B,6
  9.     CALL    MVDN
  10.     POP    H    ;GET OTHER ADDRESS BACK
  11.     PUSH    H
  12.     LXI    D,TEMP1
  13.     CALL    MVDN
  14.     LXI    H,WORK1+11    ; GET ADDRESS TO STORE PRODUCT
  15.     LDA    TEMP1+5    ;GET MULTIPLIERS
  16.     MOV    C,A
  17.     LDA    TEMP2+5
  18.     MOV    B,A
  19.     CALL    MUL2    ;GET PARTIAL PRODUCT
  20.     MOV    M,C    ;STORE IN WORK1
  21.     DCX    H    ;UPDATE
  22.     MOV    M,B    ;STORE
  23.     DCX    H
  24.     LDA    TEMP1+4    ;GET MULTIPLIERS
  25.     MOV    C,A
  26.     LDA    TEMP2+4
  27.     MOV    B,A
  28.     CALL    MUL2    ;GET PARTIAL PRODUCT
  29.     MOV    M,C    ;STORE IN WORK1
  30.     DCX    H
  31.     MOV    M,B
  32.     DCX    H
  33.     LDA    TEMP1+3    ;GET MULTIPLIERS
  34.     MOV    C,A
  35.     LDA    TEMP2+3
  36.     MOV    B,A
  37.     CALL    MUL2    ;GET PARTIAL PRODUCT
  38.     MOV    M,C    ;STORE IN WORK1
  39.     DCX    H
  40.     MOV    M,B
  41.     DCX    H
  42.     LDA    TEMP1+2    ;GET MULTIPLIERS
  43.     MOV    C,A
  44.     LDA    TEMP2+2
  45.     MOV    B,A
  46.     CALL    MUL2    ;GET PARTIAL PRODUCT
  47.     MOV    M,C    ;STORE IN WORK1
  48.     DCX    H
  49.     MOV    M,B
  50.     INX    H    ;GET READY FOR ADDING
  51.     INX    H
  52.     LDA    TEMP1+3    ;GET MULTIPLIERS
  53.     MOV    C,A
  54.     LDA    TEMP2+2
  55.     MOV    B,A
  56.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  57.     LDA    TEMP1+2    ;GET MULTIPLIERS
  58.     MOV    C,A
  59.     LDA    TEMP2+3
  60.     MOV    B,A
  61.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  62.     INX    H    ;GET NEXT COLUMN
  63.     LDA    TEMP1+2    ;GET MULTIPLIERS
  64.     MOV    C,A
  65.     LDA    TEMP2+4    
  66.     MOV    B,A
  67.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  68.     LDA    TEMP1+4    ;GET MULTIPLIERS
  69.     MOV    C,A
  70.     LDA    TEMP2+2
  71.     MOV    B,A
  72.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  73.     INX    H    ;GET NEXT COLUMN
  74.     LDA    TEMP1+2    ;GET MULTIPLIERS
  75.     MOV    C,A
  76.     LDA    TEMP2+5
  77.     MOV    B,A
  78.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  79.     LDA    TEMP1+3    ;GET MULTIPLIERS
  80.     MOV    C,A
  81.     LDA    TEMP2+4
  82.     MOV    B,A
  83.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  84.     LDA    TEMP1+4    ;GET MULTIPLIERS
  85.     MOV    C,A
  86.     LDA    TEMP2+3
  87.     MOV    B,A
  88.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  89.     LDA    TEMP1+5    ;GET MULTIPLIERS
  90.     MOV    C,A
  91.     LDA    TEMP2+2    
  92.     MOV    B,A
  93.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  94.     INX    H    ;GET NEXT COLUMN
  95.     LDA    TEMP1+3    ;GET MULTIPLIERS
  96.     MOV    C,A
  97.     LDA    TEMP2+5
  98.     MOV    B,A
  99.     CALL    FMUL1    ;ADD PARTIAL PRODUCT
  100.     LDA    TEMP1+5    ;GET MULTIPLIERS
  101.     MOV    C,A
  102.     LDA    TEMP2+3
  103.     MOV    B,A
  104.     CALL    FMUL1
  105.     INX    H    ;GET LAST COLUMN
  106.     LDA    TEMP1+4    ;GET MULTIPLIERS
  107.     MOV    C,A
  108.     LDA    TEMP2+5
  109.     MOV    B,A
  110.     CALL    FMUL1
  111.     LDA    TEMP1+5    ;GET MULTIPLIERS
  112.     MOV    C,A
  113.     LDA    TEMP2+4
  114.     MOV    B,A
  115.     CALL    FMUL1
  116.     POP    H    ;RESTORE REGISTERS
  117.     POP    D
  118.     RET        ;DONE!!!
  119. FMUL1    CALL    MUL2    ;GET PRODUCT
  120.     PUSH    H    ;SAVE INDEX
  121.     MOV    A,C    ;ADD TO WORK1
  122.     ADD    M
  123.     DAA        ;BCD ADJUST
  124.     MOV    M,A    ;STUFF IT BACK
  125. FMUL3    DCX    H    ;GET NEXT BYTE ADDRESS
  126.     MOV    A,B    ;ADD IT
  127.     ADC    M
  128.     DAA        ;BCD ADJUST
  129.     MOV    M,A    ;STUFF IT BACK
  130.     JNC    FMUL2    ;DONE
  131.     MVI    B,0    ;CLEAR B
  132.     JMP    FMUL3    ;LOOP TO PROPAGATE CARRY
  133. FMUL2    POP    H    ;RESTORE INDEX
  134.     RET        ;GO BACK
  135. * RTN. B.12
  136. * FLOATING POINT MULTIPLY
  137. * (HL) TIMES (DE) TO (BC)
  138. FLML    PUSH    B    ;SAVE DESTINATION
  139.     CALL    FMUL    ;MULTIPLY MANTISSA'S
  140.     LDA    WORK1+4    ;GET BYTE TO SEE WHERE TO ADD ROUNDING
  141.     ANI    0F0H    ;STRIP OFF UPPER DIGIT
  142.     MVI    A,50H    ;GET ROUNDING NUMBER
  143.     JNZ    FLML1    ;OK, WE GOT THE RIGHT ONE
  144.     MVI    A,05H    ;REPLACE WITH THE LOWER 5
  145. FLML1    PUSH    H    ;SAVE REGISTER
  146.     LXI    H,WORK1+8    ;GET READY TO ADD ROUNDING
  147. FLML2    ADD    M    ;ADD A BYTE
  148.     DAA        ;BCD ADJUST
  149.     MOV    M,A    ;PUT IT BACK
  150.     DCX    H    ;SET UP FOR NEXT BYTE
  151.     MVI    A,1    ;SET UP FOR CARRY PROPAGATE
  152.     JC    FLML2    ;LOOP IF CARRY UP
  153.     LXI    H,WORK1    ;SET UP TO CLEAR TOP OF BUFFER
  154.     MVI    A,4    ;NUMBER OF BYTES
  155.     CALL    ZERO    ;CLEAR IT
  156.     POP    H    ;RESTORE REGISTER
  157.     PUSH    D    ;SAVE LOCATION
  158.     LXI    D,WORK1    ;GET LOCATION OF WORK1 TO DE
  159.     CALL    NORM    ;NORMALIZE WORK1
  160.     POP    H    ;GET LOCATION BACK
  161.     PUSH    D    ;SAVE MANTISSA LOCATION
  162.     MOV    D,M    ;GET SIGNS AND EXPONENTS TO DE
  163.     INX    H
  164.     MOV    E,M
  165.     XRA    A    ;CLEAR A
  166.     STA    MERR    ;CLEAR THE ERROR FLAG
  167.     CALL    EXAD    ;ADD THE EXPONENTS
  168.     LXI    D,1    ;SET UP TO CORRECT NORMALIZATION
  169.     CALL    EXAD    ;CORRECTION
  170.     POP    D    ;GET BACK MANTISSA LOCATION
  171.     LDA    TEMP1    ;GET SIGNS BYTE
  172.     LXI    H,TEMP2    ;GET ADDRESS OF THE OTHER
  173.     XRA    M    ;COMPUTE SIGN OF RESULT
  174.     ANI    80H    ;STRIP OFF ALL BUT SIGN BIT
  175.     ORI    03H    ;PUT IN ID BITS
  176.     MOV    H,A    ;SAVE IT
  177.     MOV    A,B    ;GET EXPONENT SIGN
  178.     ANI    40H    ;STRIP ALL BUT EXPONENT SIGN
  179.     ORA    H    ;PUT IN OTHER BITS
  180.     POP    H    ;GET DESTINATION
  181.     MOV    M,A    ;STORE SIGNS BYTE
  182.     INX    H
  183.     MOV    M,C    ;STORE EXPONENT BYTE
  184.     INX    H
  185.     XCHG        ;SWAP ADDRESSES FOR MOVE
  186.     LXI    B,4    ;NUMBER OF BYTES TO MOVE
  187.     CALL    MVDN    ;MOVE THE MANTISSA IN
  188.     XCHG        ;SEE IF IT'S A FLOATING ZERO
  189.     MOV    A,M
  190.     DCX    H
  191.     DCX    H
  192.     ANA    A
  193.     RNZ        ;NOPE
  194.     XCHG
  195.     LXI    H,ZERO0
  196.     CALL    MOVE
  197.     RET        ;DONE
  198. * RTN. B.51
  199. * SQUARE ROOT EXTRACTION
  200. * SQR(HL) TO (DE)
  201. SQUR    PUSH    D    ;SAVE DESTINATION
  202.     PUSH    H    ;SAVE N
  203.     MOV    A,M
  204.     ANA    A    ;SEE IF THIS IS A MINUS NUMBER
  205.     MVI    B,39H    ;JUST IN CASE
  206.     JM    ERROR    ;CAN'T HAVE A SQUARE ROOT OF A MINUS NUMBER, ROCK!
  207.     LXI    D,TMP5    ;SET FIRST GUESS TO N
  208.     LXI    B,6    ;NUMBER OF BYTES
  209.     CALL    MOVE    ;MOVE IT IN, BOYS
  210.     LXI    D,ZERO0    ;CHECK FOR INPUT=0
  211.     CALL    CMPR
  212.     JZ    SQUR2    ;SURE IS
  213. SQUR1    LXI    H,TMP5    ;TMP6=TMP5*TMP5
  214.     LXI    B,TMP6
  215.     MOV    E,L
  216.     MOV    D,H
  217.     CALL    MULER
  218.     LXI    B,TMP6    ;COMPUTE DELTA Y
  219.     POP    H    ;GET N
  220.     PUSH    H    ;SAVE IT AGAIN
  221.     MOV    E,C
  222.     MOV    D,B
  223.     CALL    SUBER
  224.     LXI    B,TMP6    ;COMPUTE DELTA X BY DELTA Y/SLOPE
  225.     MOV    L,C
  226.     MOV    H,B
  227.     LXI    D,TWO22
  228.     CALL    DIVER
  229.     LXI    B,TMP6
  230.     MOV    L,C
  231.     MOV    H,B
  232.     LXI    D,TMP5    
  233.     CALL    DIVER    ;DIVIDE BY GUESS
  234.     CALL    TRMN1    ;CHECK FOR DONENESS
  235.     JC    SQUR2    ;AHHH, DONE TO A T
  236.     LXI    B,TMP5
  237.     LXI    D,TMP6    ;ADD DELTA X FOR NEXT GUESS
  238.     MOV    L,C
  239.     MOV    H,B
  240.     CALL    ADDER
  241.     JMP    SQUR1    ;TRY AGAIN
  242. SQUR2    POP    H    ;CLEAN UP THE STACK
  243.     POP    D    ;GET THE DESTINATION
  244.     LXI    H,TMP5    ;GET THE SOURCE
  245.     LXI    B,6    ;NUMBER OF BYTES
  246.     MOV    A,M    ;CLEAR ANY MINUS SIGN
  247.     ANI    7FH
  248.     MOV    M,A
  249.     CALL    MOVE    ;MOVE IT IN
  250.     RET        ;ALL DONE!
  251. * RTN. B.13
  252. * UNPACK PACKED BCD
  253. * HL = SOURCE ADDRESS
  254. * DE = DESTINATION ADDRESS
  255. * B  = NUMBER OF SOURCE BYTES TO UNPACK
  256. UNPK    MOV    A,M    ;GET A PACKED BYTE
  257.     MOV    C,A    ;SAVE IT IN C
  258.     RLC        ;GET UPPER DIGIT TO BOTTOM
  259.     RLC
  260.     RLC
  261.     RLC
  262.     ANI    0FH    ;STRIP OFF UPPER DIGIT
  263.     STAX    D    ;STORE TO DESTINATION
  264.     INX    D    ;UPDATE INDEX
  265.     MOV    A,C    ;GET PACKED BYTE AGAIN
  266.     ANI    0FH    ;STRIP OFF UPPER DIGIT
  267.     STAX    D    ;STORE TO DESTINATION
  268.     INX    D    ;UPDATE INDEXES
  269.     INX    H
  270.     DCR    B    ;CHECK BYTES COUNTER
  271.     JNZ    UNPK    ;LOOP FOR MORE BYTES TO UNPACK
  272.     RET        ;ALL DONE
  273. * RTN. B.14
  274. * POWERS OF TWO GENERATOR
  275. * ASSUMES NUMBER IN WORK 2+6 THROUGH WORK 2+11
  276. * POWERS OF TWO TO WORK 1+0 THROUGH WORK 2+5
  277. PWER    MVI    B,18    ;INITIALIZE BYTE COUNTER
  278.     LXI    H,WORK2+11    ;INITIALIZE SOURCE COUNTER
  279.     LXI    D,WORK2+5    ;INITIALIZE DESTINATION COUNTER
  280.     XRA    A    ;CLEAR CARRY
  281. PWER1    MOV    A,M    ;GET A BYTE
  282.     ADC    A    ;DOUBLE IT, WITH CARRY
  283.     DAA        ;BCD ADJUST
  284.     STAX    D    ;STORE IT TO DESTINATION
  285.     DCX    H    ;UPDATE INDEXES
  286.     DCX    D
  287.     DCR    B    ;CHECK BYTES COUNTER
  288.     JNZ    PWER1    ;LOOP FOR MORE ADDING TO DO
  289.     RET        ;DONE
  290. * RTN. B.15
  291. * DIVIDE TEST AND SUBTRACT
  292. * HL = FIRST DIGIT OF TEST NUMBER
  293. * DE = FIRST DIGIT OF DIVIDEND
  294. *  C = DIGIT OF QUOTIENT SO FAR
  295. * QFLAG = NUMBER OF DIVISOR DIGITS + 1
  296. * SIGN FLAG IS SET ON EXIT IF NO SUBTRACT WAS PERFORMED
  297. TSTR    PUSH    D    ;SAVE DIVIDEND INDEX
  298.     LDA    QFLAG    ;GET NUMBER OF BYTES TO TEST
  299.     DCR    A    ;CORRECT FOR LAST ADDRESS OFFSET
  300.     MOV    B,A    ;PUT IT IN B
  301. TSTR1    LDAX    D    ;GET A DIVIDEND BYTE
  302.     SUB    M    ;COMPARE WITH DIVISOR POWER
  303.     JM    TSTR4    ;JUMP IF DIVIDEND SMALLER
  304.     JNZ    TSTR6    ;JUMP IF DIVIDEND LARGER
  305.     INX    D    ;UPDATE INDEXES
  306.     INX    H
  307.     DCR    B    ;TEST BYTES COUNTER
  308.     JNZ    TSTR1    ;LOOP FOR MORE TESTING
  309. TSTR7    LDA    QFLAG    ;OK, NUMBER FITS, SO SUBTRACT IT
  310.     MOV    B,A    ;PUT NUMBER OF BYTES TO SUBTRACT IN B
  311.     XRA    A    ;CLEAR CARRY FLAG
  312. TSTR2    DCX    H    ;UPDATE INDEXES
  313.     DCX    D
  314.     LDAX    D    ;GET DIVIDEND BYTE
  315.     SBB    M    ;SUBTRACT POWER OF DIVISOR
  316.     JP    TSTR3    ;JUMP IF NO BORROW
  317.     ADI    10    ;CORRECT FOR DECIMAL
  318. TSTR3    STAX    D    ;STORE RESULT
  319.     DCR    B    ;CHECK BYTES COUNTER
  320.     JNZ    TSTR2    ;LOOP FOR MORE BYTES TO SUBTRACT
  321. TSTR4    POP    D    ;RESTORE DIVIDEND INDEX
  322.     RET        ;DONE
  323. TSTR6    MOV    A,L    ;ADD OFFSET TO INDEXES
  324.     ADD    B
  325.     MOV    L,A    ;PUT IT BACK
  326.     JNC    TSTR5    ;NO CARRY
  327.     INR    H    ;PROPAGATE CARRY
  328. TSTR5    MOV    A,E    ;AND THE OTHER ONE
  329.     ADD    B
  330.     MOV    E,A
  331.     JNC    TSTR7
  332.     INR    D
  333.     JMP    TSTR7
  334. * RTN. B.16
  335. * DIVIDE MANTISSAS FOR FLOATING POINT DIVIDE
  336. * ASSUMES:
  337. * WORK4 HAS POWERS OF TWO OF DIVISOR
  338. * WORK3 HAS UNPACKED DIVIDEND IN +1 THROUGH +8
  339. * QUOTIENT WILL BE IN WORK5 ON EXIT, +0 WILL BE
  340. * NONZERO, QFLAG WILL BE ZERO IF FIRST DIGIT
  341. * OF QUOTIENT WAS ZERO
  342. DIV1A    MVI    A,0FFH    ;SET A NONZERO
  343.     STA    ZFRST    ;SET ZFRST NONZERO
  344.     LXI    D,WORK3    ;GET FIRST ADDRESS OF DIVIDEND
  345.     XRA    A    ;CLEAR A AND SET ZERO FLAG
  346.     LXI    H,WORK5    ;GET ADDRESS OF FIRST QUOTIENT DIGIT
  347. DIV10    PUSH    H    ;SAVE REGISTERS
  348.     PUSH    PSW
  349.     MVI    C,0    ;SET QUOTIENT DIGIT TO 0
  350.     LXI    H,WORK4+2    ;GET X8 ADDRESS
  351.     CALL    TSTR    ;CHECK IT
  352.     JM    DIV11    ;JUMP IF IT DIDN'T FIT
  353.     MVI    A,8    ;MOVE BIT INTO C IF IT DID FIT
  354.     ORA    C
  355.     MOV    C,A
  356. DIV11    LXI    H,WORK4+14    ;GET X4 ADDRESS
  357.     CALL    TSTR    ;CHECK IT
  358.     JM    DIV12    ;JUMP IF IT DIDN'T FIT
  359.     MVI    A,4    ;MOVE BIT INTO C IF IT DID FIT
  360.     ORA    C
  361.     MOV    C,A
  362. DIV12    LXI    H,WORK4+26    ;GET X2 ADDRESS
  363.     CALL    TSTR    ;CHECK IT
  364.     JM    DIV13    ;JUMP IF IT DIDN'T FIT
  365.     MVI    A,2    ;MOVE BIT INTO C IF IT DID FIT
  366.     ORA    C
  367.     MOV    C,A
  368. DIV13    LXI    H,WORK4+38    ;GET X1 ADDRESS
  369.     CALL    TSTR    ;CHECK IT
  370.     JM    DIV14    ;JUMP IF IT DIDN'T FIT
  371.     MVI    A,1    ;MOVE BIT INTO C IF IT DID FIT
  372.     ORA    C
  373.     MOV    C,A
  374. DIV14    INX    D    ;UPDATE DIVIDEND INDEX
  375.     POP    PSW    ;RESTORE REGISTER
  376.     POP    H
  377.     JZ    DIV15    ;JUMP IF NO SIGNIFICANT DIGITS YET
  378. DIV16    MOV    M,C    ;STORE QUOTIENT DIGIT
  379.     INR    A    ;INCREMENT SIGNIFICANT DIGIT COUNTER
  380.     INX    H    ;INCREMENT QUOTIENT INDEX
  381.     CPI    9    ;CHECK TO SEE IF WE ARE DONE
  382.     JNZ    DIV10    ;NOPE, SO LOOP FOR MORE
  383.     RET        ;DONE
  384. DIV15    DCR    C    ;CHECK FOR C = 0
  385.     INR    C    ;RESTORE VALUE
  386.     JNZ    DIV16    ;NOPE, WASN'T 0, SO STORE IT
  387.     STA    ZFRST    ;OOPS, GOT AN INSIGNIFICANT 0
  388.     JMP    DIV10    ;LOOP FOR NEXT DIGIT
  389. * RTN. B.17
  390. * FP DIVIDE
  391. * (HL)/(DE) TO (BC)
  392. DIV2A    PUSH    B    ;SAVE PARAMETERS
  393.     PUSH    H
  394.     PUSH    D
  395.     INX    D    ;CHECK FOR DIVIDE BY ZERO
  396.     INX    D
  397.     LDAX    D    ;GET THE MSD OF MANTISSA
  398.     ANA    A    ;SET FLAGS
  399.     JZ    DERR    ;YUP, SURE WAS ZERO
  400.     MVI    A,10    ;SET UP NUMBER OF DIGITS FLAG
  401.     STA    QFLAG
  402.     XRA    A    ;CLEAR SOME BYTES
  403.     STA    MERR    ;CLEAR ERROR FLAG
  404.     STA    WORK2+6
  405.     STA    WORK2+7
  406.     MVI    A,18    ;ZERO OUT 18 BYTES
  407.     PUSH    H    ;SAVE HL
  408.     LXI    H,WORK3
  409.     CALL    ZERO
  410.     POP    H    ;RESTORE HL
  411.     LXI    D,WORK3+1    ;GET ADDRESS FOR UNPACKED DIVIDEND
  412.     MVI    B,4    ;NUMBER OF BYTES
  413.     INX    H    ;GET MANTISSA ADDRESS
  414.     INX    H
  415.     MOV    A,M    ;GET THE MSD
  416.     ANA    A    ;SET FLAGS
  417.     JNZ    DIV2G    ;JUMP IF DIVIDEND IS NOT ZERO
  418.     POP    H    ;CLEAN UP STACK
  419.     POP    H
  420.     POP    H    ;GET DESTINATION ADDRESS
  421.     MVI    M,3    ;STORE FLOATING POINT BITS
  422.     MVI    A,5    ;NUMBER OF BYTES
  423.     INX    H    ;GET EXPONENT LOCATION
  424.     CALL    ZERO    ;ZERO IS STORED
  425.     RET        ;DONE....
  426. DIV2G    CALL    UNPK    ;UNPACK IT
  427.     XRA    A    ;CLEAR OUT THE TRAILING BYTE
  428.     STAX    D
  429.     POP    H    ;GET DIVISOR ADDRESS
  430.     PUSH    H    ;SAVE IT AGAIN
  431.     INX    H    ;GET MANTISSA ADDRESS
  432.     INX    H
  433.     LXI    D,WORK2+8    ;GET ADDRESS TO STORE IT
  434.     LXI    B,4    ;NUMBER OF BYTES TO MOVE
  435.     CALL    MVDN    ;MOVE IT
  436.     CALL    PWER    ;COMPUTE X2,X4,X8
  437.     LXI    H,WORK1    ;SET UP TO UNPACK POWERS OF TWO OF DIVISOR
  438.     LXI    D,WORK4-1
  439.     MVI    B,24    ;NUMBER OF BYTES TO UNPACK
  440.     CALL    UNPK    ;UNPACK IT
  441.     CALL    DIV1A    ;DIVIDE THE MANTISSAS
  442.     POP    H    ;GET LOCATIONS AGAIN
  443.     POP    D
  444.     PUSH    D    ;SAVE THEM
  445.     PUSH    H
  446.     MOV    B,M    ;GET SIGNS AND EXPONENTS
  447.     INX    H
  448.     MOV    C,M
  449.     XCHG
  450.     MOV    D,M
  451.     INX    H
  452.     MOV    E,M
  453.     MVI    A,40H    ;CHANGE EXPONENT SIGN
  454.     XRA    B
  455.     MOV    B,A    ;PUT IT BACK
  456.     CALL    EXAD    ;ADD EXPONENTS
  457.     LDA    ZFRST    ;CHECK TO SEE IF THERE WAS A 0 FIRST
  458.     ANA    A    ;SET FLAGS
  459.     JNZ    DIV22    ;NOPE, SO SKIP THE EXPONENT OFFSET
  460.     LXI    D,4001H    ;SET UP A -1 EXPONENT
  461.     CALL    EXAD    ;ADD IN THE OFFSET
  462. DIV22    POP    H    ;GET LOCATIONS BACK
  463.     POP    D
  464.     LDAX    D    ;GET MANTISSA SIGN
  465.     XRA    M
  466.     ANI    80H    ;STRIP OFF THE SIGN
  467.     PUSH    PSW
  468.     MOV    A,B    ;GET COMPUTED SIGN
  469.     ANI    7FH    ;STRIP OFF ALL BUT SIGN
  470.     ORI    3    ;SET IN FLOATING POINT BITS
  471.     MOV    B,A    ;PUT IT BACK
  472.     POP    PSW
  473.     ORA    B    ;PUT THE TWO TOGETHER
  474.     POP    H    ;GET DESTINATION
  475.     MOV    M,A    ;STORE SIGNS BYTE
  476.     INX    H    ;UPDATE INDEX
  477.     MOV    M,C    ;STORE EXPONENT
  478.     INX    H    ;GET MANTISSA LOCATION
  479.     XCHG        ;SET UP FOR PACK
  480.     XRA    A    ;SET UP FOR ROUNDING
  481.     STA    WORK5-1    ;CLEAR EXTRA DIGIT
  482.     MVI    A,5    ;ROUNDING CONSTANT
  483.     LXI    H,WORK5+8    ;GET ADDRESS OF LSD+1
  484.     ANA    A    ;CLEAR CARRY
  485. DIV2B    ADC    M    ;ADD A BYTE
  486.     CPI    10    ;CHECK FOR OVERFLOW
  487.     JM    DIV2C    ;SKIP CORRECTION IF NO OVERFLOW
  488.     SBI    10    ;OFFSET
  489. DIV2C    CMC        ;ADJUST CARRY
  490.     MOV    M,A    ;STORE THE RESULT
  491.     MVI    A,0    ;CLEAR A
  492.     DCX    H    ;UPDATE INDEX
  493.     JC    DIV2B    ;LOOP FOR MORE CARRY PROPAGATE
  494.     LXI    H,WORK5-1    ;SET UP SOURCE ADDRESS
  495.     MOV    A,M    ;GET THE BYTE
  496.     ANA    A    ;CHECK FOR ZERO
  497.     JNZ    DIV2D    ;YUP, IT'S ZERO, SO DON'T CORRECT
  498.     INX    H    ;CORRECT FOR REAL FIRST DIGIT
  499. DIV2D    MVI    C,4    ;NUMBER OF BYTES TO PACK
  500.     CALL    PACK    ;PACK THEM
  501.     RET
  502. * RTN. B.18
  503. * PACK BCD DIGITS
  504. * HL = SOURCE
  505. * DE = DESTINATION
  506. *  C = NUMBER OF BYTES TO PACK
  507. PACK    MOV    A,M    ;GET A BYTE
  508.     RLC        ;SHIFT INTO UPPER HALF
  509.     RLC
  510.     RLC
  511.     RLC
  512.     INX    H    ;UPDATE INDEX
  513.     ORA    M    ;OR IN THE LOWER DIGIT
  514.     STAX    D    ;STORE IT TO DESTINATION
  515.     INX    H    ;UPDATE INDEXES
  516.     INX    D
  517.     DCR    C    ;CHECK BYTES COUNTER
  518.     JNZ    PACK    ;LOOP IF MORE TO DO
  519.     RET        ;DONE
  520. DERR    MVI    A,4    ;SET ERROR FLAG
  521.     STA    MERR
  522.     POP    D    ;CLEAN UP STACK
  523.     POP    H
  524.     POP    B
  525.     RET        ;ERROR RETURN
  526. * RTN. B.19
  527. * INTEGER ADD AND SUBTRACT
  528. * (HL)+-(DE)=(BC)
  529. ISUB    PUSH    B    ;SUBTRACT ENTRANCE
  530.     PUSH    H    ;SAVE REGISTERS
  531.     XCHG        ;SET UP TO MOVE SUBTRACTED VALUE
  532.     LXI    D,TEMP1    ;GET DESTINATION ADDRESS
  533.     LXI    B,6    ;NUMBER OF BYTES
  534.     CALL    MVDN    ;MOVE IT
  535.     MVI    A,80H    ;MASK MANTISSA SIGN BIT
  536.     XCHG        ;PUT THE ADDRESS IN HL
  537.     XRA    M    ;CHANGE THE SIGN BIT
  538.     MOV    M,A    ;PUT IT BACK
  539.     POP    D    ;RESTORE REGISTERS
  540.     POP    B    
  541. IADD    XRA    A    ;CLEAR A
  542.     STA    ASFLG    ;CLEAR FLAGS
  543.     STA    MERR
  544.     PUSH    B    ;SAVE DESTINATION
  545.     PUSH    H    ;SAVE ONE SOURCE
  546.     LXI    H,WORK1    ;SET UP TO CLEAR WORKING REGISTERS
  547.     MVI    A,24    ;NUMBER OF BYTES TO CLEAR
  548.     CALL    ZERO    ;CLEAR THEM
  549.     POP    H    ;RESTORE THE SOURCE
  550.     LDAX    D    ;GET A SIGNS BYTE
  551.     XRA    M    ;GET BITS DIFFERENT
  552.     ANI    80H    ;MASK OUT ALL BUT MANTISSA SIGN
  553.     JZ    IADD1+2    ;JUMP IF BOTH SIGNS ARE THE SAME
  554.     MOV    A,M    ;GET SIGNS BYTE FROM (HL)
  555.     ANI    80H    ;STRIP OFF SIGN BIT
  556.     JNZ    IADD2    ;JUMP IF (HL) IS MINUS
  557.     XCHG        ;SWAP
  558. IADD2    PUSH    D    ;SAVE LOCATIONS
  559.     PUSH    H
  560.     LXI    D,WORK1    ;GET ADDRESS TO MOVE MINUS NUMBER TO
  561.     LXI    B,6    ;NUMBER OF BYTES
  562.     CALL    MVDN    ;MOVE IT
  563.     PUSH    D    ;SAVE ADDRESS
  564.     XCHG        ;ADDRESS TO HL
  565.     INX    H    ;GET MANTISSA LOCATION
  566.     MVI    C,5    ;NUMBER OF BYTES TO COMPLEMENT
  567.     CALL    CMPL    ;GET 10'S COMPLEMENT
  568.     POP    H    ;GET BACK THE ADDRESS
  569.     XTHL        ;PUT CORRECT NUMBER ON THE STACK
  570.     MVI    A,0FFH    ;SET ASFLAG TO INDICATE A SUBTRACT
  571.     JC    IADD1    ;DON'T INDICATE SUBTRACT IF 'TWAS A ZERO
  572.     STA    ASFLG
  573. IADD1    POP    H    ;GET LOCATIONS 
  574.     POP    D
  575.     PUSH    D    ;SAVE THEM AGAIN
  576.     PUSH    H
  577.     INX    H    ;GET MANTISSA LOCATIONS
  578.     INX    D
  579.     LXI    B,WORK2+1    ;GET LOCATION TO STORE RESULT
  580.     MVI    A,5    ;NUMBER OF BYTES
  581.     CALL    FXAD    ;ADD THE MANTISSAS
  582.     POP    H    ;CLEAN UP STACK
  583.     POP    H    ;GET REFERENCE SIGN
  584.     XRA    M    ;CHANGE THE SIGN, IF NECCESARY
  585.     POP    H    ;GET LOCATION FOR RESULT OF ADDITION
  586.     MOV    M,A    ;STORE SIGNS BYTE
  587.     INX    H    ;GET MANTISSA LOCATION
  588.     XCHG        ;SET UP FOR MOVE
  589.     LXI    H,WORK2+1
  590.     LXI    B,5    ;NUMBER OF BYTES
  591.     CALL    MVDN    ;MOVE IT
  592.     LDA    WORK2    ;GET ANY OVERFLOW
  593.     ANA    A    ;SET FLAGS
  594.     RZ        ;NO OVERFLOW
  595.     STA    MERR    ;SET OVERFLOW BIT
  596.     RET        ;DONE
  597. * RTN. B.20
  598. * INTEGER MULTIPLY
  599. * (HL)*(DE)=(BC)
  600. IMUL    LDAX    D    ;GET SIGNS BYTES
  601.     XRA    M    ;GET DIFFERENT BITS
  602.     ORI    2    ;SET ID BITS
  603.     STAX    B    ;STORE TO RESULT LOCATION
  604.     INX    B    ;GET MANTISSA STORE
  605.     PUSH    B    ;SAVE DESTINATION
  606.     INX    D    ;GET MANTISSA LOCATIONS
  607.     INX    H
  608.     XRA    A    ;CLEAR A
  609.     STA    MERR    ;CLEAR ERROR FLAG
  610.     PUSH    D    ;SAVE MANTISSA LOCATIONS
  611.     PUSH    H
  612.     DCX    H    ;GET ADDRESSES FOR FIRST MULTIPLY
  613.     DCX    D
  614.     CALL    FMUL    ;MULTIPLY
  615.     POP    H    ;GET MANTISSA LOCATIONS BACK
  616.     POP    D
  617.     LDAX    D    ;CHECK FOR NONZERO BYTES IN UPPER
  618.     ORA    M
  619.     JZ    IMUL1    ;BOTH ZERO, SO NO MULTIPLY NEEDED
  620.     XRA    M    ;SEE IF HL WAS THE NONZERO ONE
  621.     JNZ    IMUL2    ;JUMP IF HL WAS ZERO
  622.     XCHG        ;MAKE HL THE ZERO ONE
  623. IMUL2    MVI    B,4    ;NUMBER OF BYTES TO CHECK
  624. IMUL4    MOV    A,M    ;GET A BYTE
  625.     ANA    A    ;SET FLAGS
  626.     JNZ    IMUL3    ;JUMP IF GUARANTEED OVERFLOW
  627.     INX    H    ;UPDATE INDEX
  628.     DCR    B    ;CHECK BYTES COUNTER
  629.     JNZ    IMUL4    ;LOOP FOR MORE BYTES TO CHECK
  630.     MOV    B,M    ;GET A BYTE TO MULTIPLY
  631.     XCHG
  632.     MOV    C,M    ;GET ANOTHER BYTE
  633.     CALL    MUL2    ;MULTIPLY THEM
  634.     LXI    H,WORK1+7    ;GET ADDRESS TO ADD TO
  635.     MOV    A,M    ;GET A BYTE
  636.     ADD    C    ;ADD
  637.     DAA        ;BCD ADJUST
  638.     MOV    M,A    ;STICK IT BACK
  639.     DCX    H    ;GET ADDRESS FOR NEXT BYTE
  640.     MOV    A,M    ;GET IT
  641.     ADC    B    ;ADD
  642.     DAA        ;BCD ADJUST
  643.     MOV    M,A    ;STICK IT BACK
  644.     DCX    H    ;CHECK BYTES FOR ALL ZEROS
  645.     ORA    M
  646.     DCX    H
  647.     ORA    M
  648.     DCX    H
  649.     ORA    M
  650.     JZ    IMUL1    ;JUMP IF ALL ZEROS (NO OVERFLOW)
  651. IMUL3    MVI    A,1    ;SET THE OVERFLOW BIT
  652.     STA    MERR
  653. IMUL1    POP    D    ;GET DESTINATION ADDRESS
  654.     LXI    H,WORK1+7    ;GET SOURCE
  655.     LXI    B,5    ;NUMBER OF BYTES
  656.     CALL    MVDN    ;MOVE IT
  657.     MVI    B,3    ;CHECK FOR OVERFLOW
  658.     XRA    A
  659. IMUL8    DCX    H    ;UPDATE INDEX
  660.     ORA    M    ;SET BITS
  661.     DCR    B    ;UPDATE COUNTER
  662.     JNZ    IMUL8    ;MORE BYTES TO CHECK
  663.     ANA    A    ;CHECK FOR OVERFLOW
  664.     RZ        ;IT'S OK
  665.     MVI    A,1    ;STORE OVERFLOW INDICATION
  666.     STA    MERR
  667.     RET        ;DONE
  668. * RTN. B.21
  669. * INTEGER DIVIDE
  670. * (HL)/(DE)=(BC)
  671. IDIV    PUSH    B    ;SAVE REGISTERS
  672.     PUSH    D    
  673.     PUSH    H
  674.     LDAX    D    ;COMPUTE NEW SIGN BYTE
  675.     XRA    M    ;GET DIFFERENT BITS
  676.     ORI    2    ;SET ID BITS
  677.     STAX    B    ;STORE TO RESULT LOCATION
  678.     MVI    A,11    ;SET UP QFLAG
  679.     STA    QFLAG
  680.     MVI    B,5    ;GET NUMBER OF MANTISSA BYTES
  681.     XRA    A    ;CLEAR A
  682.     XCHG        ;ADDRESS TO HL
  683. IDIV1    INX    H    ;UPDATE INDEX
  684.     ORA    M    ;SEE IT BYTE IS ZERO
  685.     JNZ    IDIV2    ;JUMP IF NOT ZERO
  686.     DCR    B    ;CHECK BYTES COUNTER
  687.     JNZ    IDIV1    ;LOOP FOR MORE BYTES TO CHECK
  688.     POP    H    ;CLEAN UP STACK
  689.     POP    H
  690.     POP    H
  691.     MVI    A,4    ;SET ERROR FLAG FOR DIVIDED BY ZERO
  692.     STA    MERR
  693.     RET        ;ERROR EXIT
  694. IDIV2    XRA    A    ;CLEAR A
  695.     STA    MERR    ;CLEAR ERROR FLAG
  696.     STA    WORK2+6    ;CLEAR BYTES
  697.     MVI    A,18    ;CLEAR OUT QUOTIENT REGISTER
  698.     LXI    H,WORK3
  699.     CALL    ZERO
  700.     POP    H    ;GET DIVIDEND ADDRESS
  701.     LXI    D,WORK3+1    ;GET DESTINATION ADDRESS
  702.     MVI    B,5    ;NUMBER OF BYTES TO UNPACK
  703.     INX    H    ;GET MANTISSA ADDRESS
  704.     CALL    UNPK    ;UNPACK
  705.     POP    H    ;GET DIVISOR ADDRESS
  706.     INX    H    ;GET MANTISSA ADDRESS
  707.     LXI    D,WORK2+7    ;GET ADDRESS TO MOVE IT TO
  708.     LXI    B,5    ;NUMBER OF BYTES TO MOVE
  709.     CALL    MVDN    ;MOVE IT IN
  710.     CALL    PWER    ;GENERATE POWERS OF TWO OF DIVISOR
  711.     LXI    H,WORK1    ;SET UP TO UNPACK INTO WORK4
  712.     LXI    D,WORK4
  713.     MVI    B,24
  714.     CALL    UNPK    ;UNPACK IT
  715.     LXI    D,WORK4+38    ;SET UP LOOP TO FIND MAGNITUDE OF QUOTIENT
  716.     LXI    H,WORK5    ;QUOTIENT FIRST DIGIT
  717.     MVI    C,0    ;0 TO DIGIT COUNTER
  718. IDIV3    LDAX    D    ;GET A BYTE
  719.     ANA    A    ;SET FLAGS
  720.     JNZ    IDIV4    ;AH, FOUND A SIGNIFICANT DIGIT AT LAST
  721.     MVI    M,0    ;STORE A ZERO IN QUOTIENT
  722.     INX    D    ;UPDATE INDEXES
  723.     INX    H
  724.     INR    C
  725.     JMP    IDIV3    ;LOOP TO CHECK NEXT DIGIT
  726. IDIV4    PUSH    H    ;SAVE QUOTIENT INDEX
  727.     MOV    L,C    ;SET UP TO MOVE POWERS BACK
  728.     MVI    H,0
  729.     PUSH    B    ;SAVE COUNT
  730.     LXI    D,WORK4    ;POWERS ADDRESS
  731.     DAD    D    ;ADD TO GET OFFSET
  732.     LXI    B,50    ;NUMBER OF BYTES
  733.     CALL    MVDN    ;MOVE BACK
  734.     LXI    H,WORK4+50    ;SET UP TO CLEAR BYTES MOVED UP
  735.     POP    B    ;GET COUNT BACK
  736.     MOV    B,C    ;SAVE IT IN B
  737. IDIV5    DCX    H    ;UPDATE INDEX
  738.     DCR    C    ;CHECK BYTES COUNTER
  739.     JM    IDIV6    ;JUMP OUT OF LOOP WHEN DONE
  740.     MVI    M,0    ;CLEAR A BYTE
  741.     JMP    IDIV5    ;LOOP BACK
  742. IDIV6    POP    H    ;GET BACK QUOTIENT INDEX
  743.     MOV    A,B    ;COMPUTE NEW QUOTIENT INDEX
  744.     ADD    B
  745.     MOV    E,A
  746.     MVI    D,0
  747.     CALL    SUB16
  748.     MVI    A,10
  749.     CALL    ADHL
  750.     LXI    D,WORK3    ;GET DIVIDEND ADDRESS
  751.     XRA    A    ;CLEAR A
  752. IDIV7    PUSH    H    ;SAVE REGISTERS FOR DIVIDE LOOP
  753.     PUSH    PSW
  754.     MVI    C,0    ;CLEAR QUOTIENT DIGIT
  755.     LXI    H,WORK4    ;GET X8 ADDRESS
  756.     CALL    TSTR    ;SEE IF IT WILL FIT
  757.     JM    IDIV8    ;NOPE
  758.     MOV    A,C    ;OR IN AN 8
  759.     ORI    8
  760.     MOV    C,A
  761. IDIV8    LXI    H,WORK4+12    ;GET X4 ADDRESS
  762.     CALL    TSTR    ;SEE IF IT WILL FIT
  763.     JM    IDIV9    ;NOPE
  764.     MOV    A,C    ;OR IN A 4
  765.     ORI    4
  766.     MOV    C,A
  767. IDIV9    LXI    H,WORK4+24    ;GET X2 ADDRESS
  768.     CALL    TSTR    ;SEE IF IT WILL FIT
  769.     JM    IDIVA    ;NOPE
  770.     MOV    A,C    ;OR IN A 2
  771.     ORI    2
  772.     MOV    C,A
  773. IDIVA    LXI    H,WORK4+36    ;GET X1 ADDRESS
  774.     CALL    TSTR    ;SEE IF IT WILL FIT
  775.     JM    IDIVB    ;NOPE
  776.     MOV    A,C    ;OR IN A 1
  777.     ORI    1
  778.     MOV    C,A
  779. IDIVB    POP    PSW    ;RESTORE REGISTERS
  780.     POP    H
  781.     MOV    M,C    ;STORE THE QUOTIENT DIGIT
  782.     INX    D    ;UPDATE INDEXES
  783.     INX    H
  784.     INR    A    ;UPDATE DIGIT COUNTER
  785.     CPI    11    ;ARE WE DONE??
  786.     JNZ    IDIV7    ;NO, SO LOOP FOR MORE DIGITS
  787.     POP    D    ;GET DESTINATION
  788.     INX    D    ;CORRECT FOR MANTISSA LOCATION
  789.     LXI    H,WORK5    ;GET SOURCE
  790.     MVI    C,5    ;NUMBER OF BYTES
  791.     CALL    PACK    ;PACK THE RESULT
  792.     RET        ;DONE!!
  793. * MATH MODULE
  794. * RTN. B.22 
  795. * CONVERT INTEGER TO FLOATING POINT
  796. * (HL) TO (DE)
  797. INFL    PUSH    D    ;SAVE LOCATIONS
  798.     PUSH    H
  799.     LXI    D,WORK1    ;GET ADDRESS TO UNPACK INTO
  800.     MVI    B,5    ;NUMBER OF BYTES TO UNPACK
  801.     INX    H    ;GET THE MANTISSA LOCATION
  802.     CALL    UNPK    ;UNPACK THE INTEGER
  803.     MVI    A,10    ;SET UP TO CLEAR SOME MEMORY
  804.     XCHG        ;GET ADDRESS TO HL
  805.     CALL    ZERO    ;CLEAR 10 BYTES AFTER UNPACKED NUMBER
  806.     LXI    H,WORK1    ;GET ADDRESS OF FIRST UNPACKED DIGIT
  807.     MVI    B,9H    ;A BCD 9 TO B
  808. INFL1    MOV    A,M    ;GET A BYTE
  809.     ANA    A    ;SET FLAGS
  810.     JNZ    INFL2    ;AH, A SIGNIFICANT DIGIT!!
  811.     MVI    A,99H    ;SUBTRACT 1 FROM B, IN BCD
  812.     ADD    B
  813.     DAA        ;BCD ADJUST
  814.     MOV    B,A    ;STUFF IT BACK
  815.     INX    H    ;UPDATE INDEX
  816.     JC    INFL1    ;LOOP IF B IS NOT 0 YET
  817.     MVI    B,0    ;SEND A REAL 0 TO B
  818. INFL2    POP    D    ;GET INTEGER LOCATION
  819.     LDAX    D    ;GET SIGNS BYTE
  820.     ORI    1    ;SET LSB FOR FLOATING POINT ID
  821.     POP    D    ;GET RESULT DESTINATION
  822.     STAX    D    ;STORE ID BYTE
  823.     INX    D    ;GET LOCATION FOR EXPONENT
  824.     MOV    A,B    ;EXPONENT TO B
  825.     STAX    D    ;STORE IT
  826.     INX    D    ;LOCATION FOR MANTISSA
  827.     MVI    C,4    ;NUMBER OF BYTES
  828.     CALL    PACK    ;PACK IN THE MANTISSA
  829.     RET        ;DONE
  830. * RTN. B.23
  831. * CONVERT FLOATING POINT TO INTEGER
  832. * (HL) TO (DE)
  833. FLIN    PUSH    D    ;SAVE DESTINATION
  834.     LXI    D,TMP11    ;MOVE THE NUMBER DOWN
  835.     LXI    B,6    ;NUMBER OF BYTES
  836.     CALL    MOVE
  837.     XCHG        ;NEW SOURCE TO HL
  838.     POP    D    ;GET DESTINATION BACK
  839.     MOV    A,M    ;GET SIGNS BYTE
  840.     ANI    0BEH    ;CONVERT TO INTEGER FORMAT
  841.     STAX    D    ;STORE IT
  842.     MOV    A,M    ;GET SIGNS BYTE AGAIN
  843.     ANI    40H    ;STRIP OFF EXPONENT SIGN BIT
  844.     JNZ    FLIN1    ;JUMP IF IT IS
  845.     INX    H    ;GET EXPONENT ADDRESS
  846.     MOV    A,M    ;GET IT
  847.     CPI    10H    ;SEE IF IT'S GREATER THAN 9 BCD
  848.     JNC    FLIN2    ;YUP, SO OVERFLOW
  849. FLIN3    MOV    B,A    ;SAVE IT TO B
  850.     MVI    A,9    ;SET UP SUBTRACT
  851.     PUSH    D    ;SAVE DESTINATION
  852.     SUB    B    ;SUBTRACT FOR AMOUNT TO SHIFT
  853.     PUSH    PSW    ;SAVE IT
  854.     INX    H    ;GET MANTISSA LOCATION
  855.     LXI    D,WORK1+8    ;SET UP TO MOVE MANTISSA
  856.     LXI    B,4    ;NUMBER OF BYTES TO MOVE
  857.     CALL    MVDN    ;MOVE IT
  858.     XCHG        ;GET ADDRESS TO HL
  859.     POP    PSW    ;GET NUMBER OF PLACES TO SHIFT
  860.     CALL    SHFT    ;SHIFT
  861.     POP    D    ;GET DESTINATION BACK
  862.     INX    D    ;GET MANTISSA LOCATION
  863.     LXI    B,5    ;NUMBER OF BYTES TO MOVE
  864.     CALL    MVDN    ;MOVE THEM IN
  865. FLIN4    LDA    TMP11    ;CHECK FOR NEGATIVE INPUT
  866.     ANA    A
  867.     RP        ;NOPE
  868.     DCX    D
  869.     LXI    H,ONEEE    ;GET CONSTANT
  870.     XCHG    
  871.     MOV    C,L
  872.     MOV    B,H
  873.     CALL    SUBER    ;SUBTRACT
  874.     RET
  875. FLIN1    XCHG        ;GET DESTINATION ADDRESS TO HL
  876.     INX    H    ;GET MANTISSA LOCATION
  877.     PUSH    H    ;SAVE MANTISSA DESTINATION
  878.     MVI    A,5    ;NUMBER OF BYTES
  879.     CALL    ZERO    ;CLEAR THEM OUT
  880.     POP    D    ;GET DESTINATION BACK
  881.     JMP    FLIN4
  882. FLIN2    MVI    A,1    ;SET OVERFLOW FLAG
  883.     STA    MERR
  884.     RET        ;DONE
  885. * RTN. B.24
  886. * CONVERT BCD EXPONENT TO BINARY
  887. * TWO DIGIT BCD NUMBER IN "A" IS CONVERTED TO BINARY
  888. * IN "A". NO OTHER REGISTERS DISTURBED
  889. * METHOD CONTRIBUTED BY SAM SINGER
  890. BCDBN    PUSH    B    ;SAVE BC
  891.     MOV    B,A    ;SAVE THE DIGITS
  892.     ANI    0F0H    ;MASK OUT THE MSD
  893.     RAR        ;EQUIVALENT TO DIGIT * 8
  894.     MOV    C,A    ;SAVE IT
  895.     RAR        ;RIGHT SHIFT TO DIVIDE
  896.     RAR        ;BY 4
  897.     ADD    C    ;DIGIT*8+DIGIT*2=DIGIT*10
  898.     MOV    C,A    ;SAVE IT
  899.     MOV    A,B    ;GET ORIGINAL DIGITS
  900.     ANI    0FH    ;MASK OUT THE LSB
  901.     ADD    C    ;ADD MSB*10
  902.     POP    B    ;RESTORE BC
  903.     RET        ;DONE.
  904. * THANKS, SAM
  905. * RTN. B.25
  906. * CONVERT NUMBER TO EQUIVALENT SIGN
  907. * (HL) TO (DE)
  908. * IF (HL)>0, (DE) WILL BE +1
  909. * IF (HL)=0, (DE) WILL BE  0
  910. * IF (HL)<0, (DE) WILL BE -1
  911. SIGN    MOV    A,M    ;GET THE ID BYTE
  912.     PUSH    D    ;SAVE DESTINATION ADDRESS
  913.     LXI    D,TMP11    ;CONVERSION REGISTER
  914.     ANI    0BEH    ;STRIP OFF FLOATING POINT BITS
  915.     STAX    D    ;STORE TO NEW LOCATION
  916.     MVI    B,4    ;SET UP BYTE COUNTER
  917. SIGN1    INX    H    ;UPDATE INDEXES
  918.     INX    D
  919.     MOV    A,M    ;GET A BYTE
  920.     ANA    A    ;SET FLAGS
  921.     JNZ    SIGN2    ;JUMP OUT OF LOOP IF NONZERO
  922.     STAX    D    ;STORE A ZERO BYTE
  923.     DCR    B    ;CHECK BYTE COUNTER
  924.     JP    SIGN1    ;LOOP IF NOT DONE YET
  925.     JMP    SIGN9    ;DONE IF 'TWAS ALL ZEROES
  926. SIGN2    DCR    B    ;SEE IF WE ARE ON THE LAST BYTE YET
  927.     JM    SIGN3    ;YUP, SO GO STORE A ONE
  928.     XRA    A    ;CLEAR A
  929.     STAX    D    ;STORE THE ZERO
  930.     JMP    SIGN1+1    ;LOOP FOR ANOTHER BYTE
  931. SIGN3    MVI    A,1    ;SET UP FOR STORING LAST BYTE
  932.     STAX    D    ;DO IT
  933. SIGN9    POP    D    ;MOVE NUMBER TO DESTINATION
  934.     LXI    H,TMP11
  935.     LXI    B,6
  936.     CALL    MOVE
  937.     RET        ;DONE.
  938. * RTN. B.26
  939. * INTEGER FUNCTION
  940. * INT(HL) TO (DE)
  941. INTG    MOV    A,M    ;CHECK TO SEE IF (HL) IS INTEGER ALREADY
  942.     ANI    1    ;STRIP OFF THE INTEGER/FLOATING BIT
  943.     JZ    INTG1    ;LEAP IF (HL) IS ALREADY AN INTEGER
  944.     CALL    FLIN    ;CONVERT TO INTEGER
  945.     RET        ;DONE
  946. INTG1    LXI    B,6    ;NUMBER OF BYTES
  947.     CALL    MVDN    ;MOVE THE INTEGER TO NEW LOCATION
  948.     RET        ;AH, FINI.
  949. * RTN. B.27
  950. * ABSOLUTE VALUE FUNCTION
  951. * ABS(HL) TO (DE)
  952. ABSLT    MOV    A,M    ;GET ID BYTE
  953.     ANI    7FH    ;STRIP OFF MANTISSA SIGN BIT
  954.     STAX    D    ;STORE IT TO NEW LOCATION
  955.     INX    D    ;GET MANTISSA LOCATIONS
  956.     INX    H
  957.     LXI    B,5    ;NUMBER OF BYTES
  958.     CALL    MVDN    ;MOVE MANTISSA (AND) EXPONENT IN
  959.     RET        ;DONE. (WHY CAN'T THEY ALL BE THIS EASY??)
  960. * RTN. B.28
  961. * CONVERT ASCII STRING AT (HL) TO NUMBER AT (DE)
  962. * CARRY SET ON EXIT IF ERROR OCCURED
  963. * ON EXIT HL IS ADDRESS OF NEXT STRING ELEMENT
  964. STNM    MOV    A,M    ;CHECK IT OUT
  965.     ANI    7FH
  966.     CPI    2DH    ;CHECK FOR MINUS SIGN
  967.     JZ    P1    ;YUP
  968.     CPI    '.'
  969.     JZ    P1
  970.     CPI    3AH
  971.     STC
  972.     RP
  973.     CPI    30H
  974.     RC
  975. P1    PUSH    H    ;SAVE LOCATIONS
  976.     PUSH    D
  977.     MVI    A,0FFH    ;PRESET COUNTERS
  978.     STA    CNVR1
  979.     STA    CNVR2
  980.     MVI    A,11    ;NUMBER OF BYTES
  981.     PUSH    H    ;SAVE AGAIN
  982.     LXI    H,WORK1    ;ADDRESS OF BUFFER
  983.     CALL    ZERO    ;CLEAR IT
  984.     POP    H    ;GET ADDRESS BACK
  985.     STA    CNVR3    ;CLEAR ZERO COUNTER
  986.     LXI    D,WORK1    ;GET BUFFER ADDRESS
  987.     LXI    B,02H    ;PRESET DIGIT COUNTER AND SIGNS
  988. STNM5    MOV    A,M    ;GET AN ASCII BYTE
  989.     ANI    7FH    ;STRIP UPPER BIT
  990.     CPI    '-'    ;SEE IF IT'S A MINUS SIGN
  991.     JZ    STNM1    ;SURE WAS
  992.     CPI    '.'    ;SEE IF IT'S A PERIOD
  993.     JZ    STNM3    ;YUP
  994.     CPI    'E'    ;SEE IF IT'S AN E
  995.     JZ    STNMA    ;LOOKS THAT WAY
  996.     CPI    '0'    ;SEE IF IT'S MAYBE A DIGIT
  997.     JM    STNM4    ;'PEARS NOT TO BE
  998.     CPI    '9'+1    ;IS IT STILL A DIGIT?
  999.     JP    STNM4    ;NOPE
  1000.     SUI    30H    ;STRIP ASCII OFFSET
  1001.     JNZ    STNM6    ;GO STORE IT
  1002.     LDA    WORK1    ;SEE IF WE ARE INTO INSIGNIFICANT ZEROES
  1003.     ANA    A    ;SET FLAGS
  1004.     MVI    A,0    ;RESTORE THE ZERO
  1005.     JNZ    STNM6    ;GO STORE IT
  1006.     LDA    CNVR3    ;INCREMENT THE LEADING ZEROES COUNTER
  1007.     INR    A
  1008.     STA    CNVR3
  1009. STNM7    INX    H    ;GET THE NEXT ASCII CHARACTER
  1010.     JMP    STNM5    ;LOOP TO PROCESS
  1011. STNM6    STAX    D    ;STORE THE CHARACTER IN THE BUFFER
  1012.     INX    D    ;UPDATE INDEX
  1013.     INR    B    ;UPDATE DIGIT COUNTER
  1014.     JMP    STNM7    ;GO GET NEXT CHARACTER
  1015. STNM1    INR    B    ;CHECK FOR B=0
  1016.     DCR    B
  1017.     JNZ    STNM4    ;NO,NO, CAN'T HAVE MINUS SIGNS IN THE MIDDLE
  1018. *             OF NUMBERS.
  1019.     MVI    A,80H    ;SET THE MINUS MANTISSA INDICATOR
  1020.     ORA    C
  1021.     MOV    C,A    ;PUT IT BACK
  1022.     JMP    STNM7    ;GO GET NEXT CHARACTER
  1023. STNMA    INX    H    ;GET CHARACTER FOLLOWING E
  1024.     MOV    A,M
  1025.     ANI    7FH    ;STRIP OFF UPPER BIT
  1026.     CPI    '-'    ;IS IT A MINUS SIGN??
  1027.     JZ    STNMB    ;SURE IS
  1028.     SUI    20H    ;IS IT A SPACE??
  1029.     JNZ    STNM9    ;NO, SO WE'VE GOT AN ERROR
  1030.     INR    A    ;ONE TO A
  1031. STNMC    ORA    C    ;SET THE EXPONENT SIGN INDICATOR
  1032.     MOV    C,A    ;PUT IT BACK
  1033.     CALL    STNMN    ;GET AND CHECK CHARACTER
  1034.     STA    CNVR4    ;SAVE THE MSD
  1035.     CALL    STNMN    ;GET AND CHECK CHARACTER
  1036.     PUSH    B    ;SAVE TEMP
  1037.     MOV    B,A    ;SAVE LSD
  1038.     LDA    CNVR4    ;GET THE MSD BACK
  1039.     RLC        ;SHIFT IT INTO UPPER POSITION
  1040.     RLC
  1041.     RLC
  1042.     RLC
  1043.     ADD    B    ;PUT IN THE LOWER DIGIT
  1044.     POP    B    ;RESTORE
  1045.     CALL    BCDBN    ;CONVERT IT TO BINARY
  1046.     STA    CNVR2    ;STORE IT
  1047.     INX    H    ;CORRECT HL TO SHOW END PROPERLY
  1048.     JMP    STNM4    ;GO FORM NUMBER
  1049. STNMB    MVI    A,41H    ;SET NEGATIVE INDICATOR
  1050.     JMP    STNMC    ;GO PROCESS EXPONENT
  1051. STNMN    INX    H    ;UPDATE INDEX
  1052.     MOV    A,M    ;GET THE CHARACTER
  1053.     ANI    7FH    ;STRIP UPPER BIT
  1054.     SUI    30H    ;IS IT LESS THAN A NUMBER
  1055.     JM    STNMO    ;SURE WAS
  1056.     CPI    10    ;IS IT MORE THAN A DIGIT?
  1057.     JP    STNMO    ;YUP
  1058.     RET        ;IT'S OK
  1059. STNMO    POP    D    ;CLEAN UP STACK
  1060. STNM9    POP    D    ;RESTORE REGISTERS FOR ERROR EXIT
  1061.     POP    H
  1062.     STC        ;SET ERROR INDICATOR
  1063.     RET        ;EXIT, STAGE AN ERROR
  1064. STNM4    MOV    A,B    ;PUT DIGIT COUNT IN A
  1065.     CPI    11    ;IS B > 10?
  1066.     JM    STNME    ;NO
  1067.     MVI    A,1    ;SET UP TO SET FLOATING FLAG
  1068.     ORA    C
  1069.     MOV    C,A    ;PUT IT BACK
  1070. STNME    MOV    A,C    ;CHECK FLOATING BIT
  1071.     ANI    1
  1072.     JZ    STNMF    ;LEAP IF THIS IS AN INTEGER
  1073.     LDA    CNVR2    ;CHECK STATE OF EXPONENT FLAG
  1074.     CPI    0FFH    ;HAS IT BEEN READ IN?
  1075.     JZ    STNMG    ;NOPE
  1076. STNML    LDA    CNVR1    ;CHECK STATE OF DECIMAL POINT FLAG
  1077.     CPI    0FFH    ;HAS IT BEEN READ IN?
  1078.     JZ    STNMH    ;NOPE
  1079. STNMI    MOV    A,C    ;CHECK SIGN OF EXPONENT
  1080.     ANI    40H
  1081.     JNZ    STNMJ    ;LEAP FOR ALTERNATE CONVERSION (NEGATIVE)
  1082.     LDA    CNVR1    ;GET CNVR1 TO B
  1083.     MOV    B,A
  1084.     LDA    CNVR2    ;GET CNVR2 TO A
  1085.     ADD    B    ;COMPUTE CNVR2+CNVR1
  1086.     DCR    A
  1087.     DCR    A
  1088.     JMP    STNMK    ;SKIP
  1089. STNMJ    LDA    CNVR3    ;GET CNVR3
  1090.     MOV    B,A    ;SAVE IT IN B
  1091.     LDA    CNVR2    ;GET CNVR2
  1092.     ADD    B    ;ADD
  1093.     MOV    B,A    ;SAVE IT IN B
  1094.     LDA    CNVR1    ;GET CNVR1
  1095.     CMA        ;2'S COMPLEMENT
  1096.     INR    A
  1097.     ADD    B
  1098. STNMK    INR    A    ;CORRECTION
  1099.     CALL    STNMP    ;CONVERT TO BCD
  1100.     POP    D    ;GET BACK ADDRESS TO STORE TO
  1101.     INX    D    ;GET EXPONENT ADDRESS
  1102.     STAX    D    ;STORE EXPONENT
  1103.     DCX    D    ;GET SIGNS LOCATION
  1104.     MOV    A,C    ;GET ID BYTE TO A
  1105.     STAX    D    ;STORE IT
  1106.     INX    D    ;GET MANTISSA LOCATION
  1107.     INX    D
  1108.     PUSH    H    ;SAVE INDEX
  1109.     LXI    H,WORK1    ;GET LOCATION OF NUMBER
  1110.     MVI    C,8    ;PRESET COUNTER
  1111. STNMW    MOV    A,M    ;GET A BYTE
  1112.     ANA    A    ;SET FLAGS
  1113.     JNZ    STNMV    ;OK, NOT ZERO
  1114.     INX    H    ;UPDATE INDEX
  1115.     DCR    C    ;UPDATE COUNTER
  1116.     JNZ    STNMW    ;CHECK ANOTHER BYTE
  1117.     DCX    D    ;GET EXPONENT LOCATION
  1118.     STAX    D    ;STORE A ZERO
  1119.     INX    D    ;GET MANTISSA LOCATION BAC
  1120. STNMV    LXI    H,WORK1    ;SOURCE
  1121.     MVI    C,4    ;NUMBER OF PACKED BYTES
  1122.     CALL    PACK    ;PACK IN THE MANTISSA
  1123.     POP    H    ;RESTORE INDEX
  1124.     POP    D    ;CLEAN UP STACK
  1125.     XRA    A    ;CLEAR CARRY
  1126.     RET        ;FLOATING POINT EXIT
  1127. STNMP    PUSH    D    ;SAVE REGISTERS
  1128.     PUSH    H
  1129.     MOV    L,A    ;PUT BINARY NUMBER IN HL
  1130.     MVI    H,0
  1131.     MVI    E,10    ;SET UP TO DIVIDE BY 10
  1132.     CALL    DIV    ;DO IT TO IT
  1133.     MOV    A,L    ;ROTATE MSD INTO UPPER POSITION
  1134.     RLC
  1135.     RLC
  1136.     RLC
  1137.     RLC
  1138.     ADD    H    ;ADD REMAINDER
  1139.     POP    H    ;RESTORE
  1140.     POP    D
  1141.     RET        ;GO BACK FROM WHENCEVER YOUSE CAME
  1142. STNMG    XRA    A    ;CLEAR CNVR2
  1143.     STA    CNVR2
  1144.     JMP    STNML    ;CONTINUE PROCESSING
  1145. STNMH    MOV    A,B    ;SEND B TO CNVR1
  1146.     STA    CNVR1
  1147.     JMP    STNMI    ;CONTINUE PROCESSING
  1148. STNM3    LDA    WORK1    ;SEE IF ANY SIGNIFICANT DIGITS YET
  1149.     ANA    A    ;SET FLAGS
  1150.     JNZ    STNMM    ;AH, THERE ARE SIGNIFICANT DIGITS
  1151.     STA    CNVR3    ;NO, SO CLEAR THE LEADING ZEROES COUNTER
  1152.     MVI    A,40H    ;SET IN EXPONENT SIGN BIT
  1153.     ORA    C
  1154.     MOV    C,A
  1155. STNMM    MVI    A,1    ;SET THE FLOATING POINT BIT
  1156.     ORA    C
  1157.     MOV    C,A    ;PUT IT BACK
  1158.     MOV    A,B    ;SEND B TO CNVR1
  1159.     STA    CNVR1
  1160.     JMP    STNM7    ;JUMP BACK TO PROCESS NEXT CHARACTER
  1161. STNMF    POP    D    ;GET LOCATION
  1162.     MOV    A,C    ;STORE ID BYTE
  1163.     STAX    D
  1164.     INX    D
  1165.     PUSH    H    ;SAVE INDEXES
  1166.     PUSH    D
  1167.     MVI    A,10    ;C=10-B
  1168.     SUB    B
  1169.     MOV    C,A
  1170.     LXI    H,WORK1+9    ;GET END OF NUMBER
  1171.     MOV    A,L    ;DE=HL-C
  1172.     SUB    C
  1173.     MOV    E,A
  1174.     MOV    A,H
  1175.     SBI    0
  1176.     MOV    D,A
  1177. STMNQ    INR    B    ;CHECK FOR B=0
  1178.     DCR    B    
  1179.     JZ    STMNR    ;GO TO STORE ZEROES
  1180.     LDAX    D    ;GET A BYTE
  1181.     MOV    M,A    ;STORE IT
  1182.     DCX    D    ;UPDATE INDEXES
  1183.     DCX    H
  1184.     DCR    B    ;UPDATE COUNTER
  1185.     JMP    STMNQ    ;LOOP FOR MORE BYTES TO MOVE
  1186. STMNR    INR    C    ;CHECK FOR C=0
  1187.     DCR    C
  1188.     JZ    STNMQ    ;ALL DONE
  1189.     MVI    M,0    ;STORE A 0
  1190.     DCX    H    ;UPDATE INDEX
  1191.     DCR    C    ;UPDATE COUNTER
  1192.     JMP    STMNR    ;LOOP FOR MORE ZEROES
  1193. STNMQ    LXI    H,WORK1    ;GET SOURCE
  1194.     MVI    C,5    ;NUMBER OF PACKED BYTES
  1195.     POP    D    ;GET DESTINATION
  1196.     CALL    PACK    ;PACK IT IN, BOYS.
  1197.     POP    H    ;RESTORE INDEX
  1198.     POP    D    ;CLEAN UP STACK
  1199.     XRA    A    ;CLEAR CARRY 
  1200.     RET        ;INTEGER EXIT
  1201. * RTN. B.29
  1202. * CONVERT NUMBER TO ASCII STRING
  1203. * NUMBER AT (HL) CONVERTED TO STRING STARTING AT (DE)
  1204. * ON EXIT, DE IS NEXT CHARACTER AFTER STRING
  1205. NMST    XRA    A    ;CLEAR A AND SOME FLAGS
  1206.     STA    CNVR5    ;CLEAR FLOATING/INTEGER FLAG
  1207.     STA    CNVR1    ;CLEAR LEADING ZEROES FLAG
  1208.     MOV    B,M    ;GET ID BYTE
  1209.     MOV    A,B    ;GET ID BYTE TO A
  1210.     ANI    80H    ;SEE IF MANTISSA IS NEGATIVE
  1211.     JZ    NMSTZ    ;SKIP IF POSITIVE
  1212.     MVI    A,'-'    ;SET UP A MINUS
  1213.     STAX    D    ;STORE TO STRING LOCATION
  1214.     INX    D    ;GET NEXT LOCATION
  1215. NMSTZ    PUSH    D    ;SAVE IT
  1216.     MOV    A,B    ;GET ID BYTE AGAIN
  1217.     ANI    1    ;SEE IF THIS IS AN INTEGER
  1218.     JZ    NMST1    ;SURE WAS!!
  1219.     INX    H    ;GET EXPONENT LOCATION
  1220.     INX    H    ;GET FIRST BYTE
  1221.     MOV    A,M    ;CHECK FOR FLOATING ZERO
  1222.     DCX    H    ;BACK TO EXPONENT
  1223.     ANA    A
  1224.     JNZ    NMS47    ;IT'S A ZERO!
  1225.     MVI    M,0    ;MAKE IT RIGHT
  1226.     DCX    H
  1227.     MVI    M,2
  1228.     JMP    NMST1    ;PROCESS AS INTEGER
  1229. NMS47    MOV    A,M    ;GET EXPONENT
  1230.     MOV    C,A    ;PUT IT IN C AND EXPONENT FLAG
  1231.     STA    CNVR4
  1232.     MOV    A,B    ;GET ID BYTE TO FLOATING/INTEGER FLAG
  1233.     STA    CNVR5
  1234.     MVI    A,1    ;GET A ONE TO DECIMAL POINT FLAG
  1235.     STA    CNVR3
  1236.     LDA    CNVRA    ;GET MAX NORMAL DISPLAY FLAG
  1237.     CMP    C    ;CHECK THIS TURKEY NUMBER'S SIZE
  1238.     JC    NMST2    ;OOPS, TOO BIG, SO EXPONENT DISPLAY
  1239.     XRA    A    ;CLEAR EXPONENT DISPLAY FLAG
  1240.     STA    CNVR5
  1241.     MOV    A,B    ;GET ID BYTE AGAIN
  1242.     ANI    40H    ;CHECK SIGN OF EXPONENT
  1243.     JNZ    NMST3    ;LEAP IF IT'S MINUS
  1244.     LDA    CNVR4    ;GET EXPONENT
  1245.     CALL    BCDBN    ;CONVERT IT TO BINARY
  1246.     INR    A    ;ADD ONE
  1247.     STA    CNVR3    ;SET DECIMAL POINT FLAG
  1248.     JMP    NMST2    ;SKIP
  1249. NMST1    INX    H    ;UPDATE INDEX
  1250.     MVI    A,10    ;TEN TO DECIMAL POINT FLAG
  1251.     STA    CNVR3
  1252.     JMP    NMST4    ;CONTINUE
  1253. NMST3    XRA    A    ;CLEAR DECIMAL POINT FLAG
  1254.     STA    CNVR3
  1255.     LDA    CNVR4    ;GET EXPONENT
  1256.     CALL    BCDBN    ;CONVERT THE THING TO BINARY
  1257.     DCR    A    ;SUBTRACT ONE
  1258.     STA    CNVR1    ;SET THE LEADING ZEROES FLAG
  1259. NMST2    INX    H    ;GET MANTISSA ADDRESS
  1260.     MVI    A,8    ;SET NUMBER OF BYTES
  1261. NMST4    STA    CNVR6    ;SET NUMBER OF DIGITS FLAG
  1262.     RRC        ;DIVIDE BY TWO
  1263.     ANI    0FH
  1264.     MOV    B,A    ;STICK IT IN B
  1265.     LXI    D,WORK1    ;SET UP TO UNPACK
  1266.     CALL    UNPK    ;DO IT
  1267.     MVI    C,10    ;SET UP TO TURN IT ALL INTO ASCII
  1268.     LXI    H,WORK1
  1269. NMST5    MOV    A,M    ;GET A BYTE
  1270.     ORI    30H    ;SET ASCII BITS
  1271.     MOV    M,A    ;PUT IT BACK
  1272.     INX    H    ;UPDATE INDEX
  1273.     DCR    C    ;CHECK NUMBER OF BYTES
  1274.     JNZ    NMST5    ;LOOP TO CONVERT MORE BYTES
  1275.     LDA    CNVR6    ;GET NUMBER OF DIGITS
  1276.     MOV    C,A    ;SEND THE MESS TO C
  1277.     LXI    H,WORK1    ;GET BUFFER LOCATION
  1278.     CALL    ADHL    ;HL=HL+A
  1279.     DCX    H
  1280. NMST6    MOV    A,M    ;GET A BYTE
  1281.     CPI    30H    ;SEE IF IT'S AN ASCII ZERO
  1282.     JNZ    NMST7    ;NO, SIREE
  1283.     DCX    H    ;WELL THEN, CHECK SOME MORE
  1284.     DCR    C    ;IS WE DONE YET???
  1285.     JNZ    NMST6    ;NO? WELL, THEN GO AND CHECK ANOTHER ONE
  1286.     MVI    C,09H
  1287. NMST7    MOV    A,C    ;STORE C IN TRAILING ZEROES FLAG
  1288.     STA    CNVR2
  1289.     LXI    H,WORK1    ;GET BUFFER START
  1290.     LXI    B,0    ;CLEAR COUNTERS
  1291.     POP    D    ;RESTORE INDEX
  1292. NMST8    LDA    CNVR3    ;GET DECIMAL POINT FLAG
  1293.     CMP    B    ;=B?
  1294.     JNZ    NMST9    ;NO, SO SKIP
  1295.     LDA    CNVR6    ;CHECK FOR FLOATING POINT
  1296.     CPI    8
  1297.     JZ    NMS00    ;SURE WAS, SO DUMP A DECIMAL POINT
  1298.     LDA    CNVR2    ;GET TRAILING ZEROES START
  1299.     CMP    B    ;ANYTHING LEFT TO PRINT?
  1300.     JZ    NMSTA    ;NOPE.
  1301. NMS00    MVI    A,'.'    ;GET AN ASCII PERIOD
  1302.     STAX    D    ;STORE IT
  1303.     INX    D    ;UPDATE INDEX
  1304. NMST9    LDA    CNVR2    ;GET TRAILING ZEROES FLAG
  1305.     CMP    B    ;ANYTHING LEFT TO PRINT??
  1306.     JZ    NMSTA    ;NOPE
  1307.     LDA    CNVR1    ;GET LEADING ZEROES FLAG
  1308.     ANA    A    ;CHECK FOR A ZERO
  1309.     JZ    NMSTB    ;SKIP IF IT'S ZERO
  1310.     PUSH    B    ;SAVE COUNTERS
  1311.     MOV    C,A    ;NUMBER OF ZEROES TO C
  1312.     MVI    A,30H    ;ASCII ZERO TO A
  1313. NMSTC    STAX    D    ;STORE A ZERO
  1314.     INX    D    ;UPDATE INDEX
  1315.     DCR    C    ;CHECK BYTES COUNTER
  1316.     JNZ    NMSTC    ;LOOP FOR MORE ZEROES
  1317.     POP    B    ;RESTORE COUNTERS
  1318.     XRA    A    ;CLEAR LEADING ZEROES FLAG
  1319.     STA    CNVR1
  1320. NMSTB    MOV    A,M    ;GET ANOTHER BYTE
  1321.     CPI    30H    ;IS IT A ZERO (ASCII)??
  1322.     JNZ    NMSTD    ;NO, NOT THIS TIME
  1323.     INR    C    ;CHECK FOR C = 0
  1324.     DCR    C
  1325.     JZ    NMSTE    ;SURE IS
  1326. NMSTD    INR    C    ;SET SIGNIFICANT DIGIT FLAG
  1327.     STAX    D    ;STORE A DIGIT
  1328.     INX    D    ;UPDATE INDEXES
  1329. NMSTE    INX    H
  1330.     INR    B    ;INCREMENT DIGIT COUNTER
  1331.     LDA    CNVR6    ;GET NUMBER OF DIGITS
  1332.     CMP    B    ;HAVE WE DONE THAT MANY?
  1333.     JNZ    NMST8    ;NO, SO LOOP FOR SOME MORE
  1334. NMSTA    LDA    CNVR2    ;CHECK FOR MORE ZEROES TO SPIT OUT
  1335.     MOV    B,A    ;SAVE IN B
  1336.     LDA    CNVR3    ;GET DECIMAL LOCATION
  1337.     SUB    B    ;SUBTRACT
  1338.     MOV    B,A    ;STICK IT IN B
  1339.     JZ    NMSTU    ;YUP
  1340.     JM    NMSTU    ;YUP
  1341. NMSTX    DCR    B    ;CHECK COUNT
  1342.     JM    NMS57    ;CONTINUE
  1343.     MVI    A,'0'    ;STORE A ZERO
  1344.     STAX    D
  1345.     INX    D    ;INCREMENT INDEX
  1346.     JMP    NMSTX    ;LOOP FOR MORE ZEROES
  1347. NMSTU    LDA    CNVR5    ;CHECK FOR EXPONENT DISPLAY
  1348.     ANA    A    ;SET FLAGS
  1349.     RZ        ;RETURN IF NO EXPONENT NECESARY
  1350.     ANI    40H    ;CHECK FOR MINUS EXPONENT
  1351.     MVI    A,'E'    ;STORE AN E
  1352.     STAX    D
  1353.     INX    D    ;UPDATE INDEX
  1354.     MVI    A,20H    ;GET A SPACE
  1355.     JZ    NMSTF    ;SKIP IF EXPONENT POSITIVE
  1356.     MVI    A,'-'    ;GET A MINUS SIGN
  1357. NMSTF    STAX    D    ;STORE THIS
  1358.     INX    D    ;INCREMENT INDEX
  1359.     LDA    CNVR4    ;GET EXPONENT
  1360.     MOV    B,A    ;PUT IT IN B
  1361.     RRC        ;SHIFT MSD INTO BOTTOM
  1362.     RRC
  1363.     RRC    
  1364.     RRC
  1365.     ANI    0FH    ;STRIP OFF UPPER
  1366.     ORI    30H    ;SET ASCII OFFSET
  1367.     STAX    D    ;STORE IT
  1368.     INX    D
  1369.     MOV    A,B    ;GET THE EXPONENT AGAIN
  1370.     ANI    0FH    ;STRIP OFF UPPER
  1371.     ORI    30H    ;SET ASCII OFFSET
  1372.     STAX    D    ;STORE IT
  1373.     INX    D    ;UPDATE INDEX
  1374.     RET        ;AHHHHH, DONE.
  1375. NMS57    LDA    CNVR6    ;SEE IF THIS IS FLOATING
  1376.     CPI    8
  1377.     JNZ    NMSTU    ;NOPE
  1378.     MVI    A,'.'    ;STUFF A PERIOD
  1379.     STAX    D
  1380.     INX    D    ;UPDATE
  1381.     JMP    NMSTU    ;CONTINUE
  1382. * MATH MODULE
  1383. * RTN. B.37
  1384. * TERMINATOR FOR TRANSCENDENTAL FUNCTIONS
  1385. * TRMN ENTRANCE CHANGES SIGNF AND CHECKS TMP6
  1386. * TRMN1 ENTRANCE JUST CHECKS TMP6
  1387. TRMN    LDA    SIGNF    ;GET THE SIGN CHANGE FLAG
  1388.     MOV    B,A    ;STICK IT IN B
  1389.     LXI    H,TMP6    ;GET ADDRESS OF TERM
  1390.     XRA    M    ;CHANGE THE SIGN BIT IF INDICATED
  1391.     MOV    M,A    ;STUFF IT BACK
  1392.     MOV    A,B    ;GET THE SIGN FLAG BACK
  1393.     XRI    80H    ;CHANGE IT
  1394.     STA    SIGNF    ;STUFF IT BACK TOO
  1395. TRMN1    LHLD    TMP5    ;GET ID BYTE AND EXPONENT
  1396.     MOV    C,H    ;MOVE TO BC
  1397.     MOV    B,L
  1398.     LHLD    TMP6    ;GET ID BYTE AND EXPONENT
  1399.     MOV    E,H    ;MOVE TO DE
  1400.     MOV    A,L    ;CHANGE EXPONENT SIGN
  1401.     XRI    40H
  1402.     MOV    D,A
  1403.     LDA    TMP6+2    ;CHECK FOR TERM=0
  1404.     ANA    A    ;SET FLAGS
  1405.     STC        ;SET THE CARRY JUST IN CASE
  1406.     RZ
  1407.     CALL    EXAD    ;ADD THE EXPONENTS
  1408.     MOV    A,B    ;CHECK THE SIGN
  1409.     ANI    40H    ;STRIP IT OFF
  1410.     RNZ        ;RETURN WITHOUT CARRY IF WAS NEGATIVE
  1411.     MOV    A,C    ;GET THE EXPONENT
  1412.     SUI    8    ;SET CARRY TO WRONG STATE
  1413.     CMC        ;SET IT RIGHT
  1414.     RET        ;DONE..
  1415. * RTN. B.38
  1416. * COMPARE (HL) AND (DE)
  1417. * ZERO SET IF (HL) EQUALS (DE)
  1418. * CARRY SET IF (HL) < (DE)
  1419. CMPR    LXI    B,TMP7    ;GET ADDRESS OF ANSWER HOME
  1420.     CALL    SUBER    ;SUBTRACT (HL)-(DE)
  1421.     LXI    H,TMP7+1    ;GET ADDRESS OF EXPONENT/MSD'S
  1422.     MVI    B,5    ;NUMBER OF BYTES TO CHECK
  1423. CMPR2    MOV    A,M    ;GET A BYTE
  1424.     ANA    A    ;SET FLAGS
  1425.     JNZ    CMPR1    ;AH,HA, IT'S NOT ZERO
  1426.     INX    H    ;UPDATE INDEX
  1427.     DCR    B    ;CHECK BYTE COUNTER
  1428.     JNZ    CMPR2    ;NOT DONE, SO LOOP FOR MORE
  1429.     RET        ;THIS EXIT IF NUMBER WAS ZERO
  1430. CMPR1    LDA    TMP7    ;CHECKING THE MANTISSA SIGN
  1431.     ANI    80H    ;STRIP IT OFF
  1432.     ORI    1    ;SET A BIT SO'S WE DON'T GET A ZERO
  1433.     RLC        ;SET THE CARRY FLAG IF 'TWAS NEGATIVE
  1434.     RET        ;THIS EXIT IF NUMBER WAS NOT ZERO
  1435. * CONSTANT 2PI
  1436. TWOPI    DB    3    ;ID BYTE
  1437.     DB    0    ;EXPONENT
  1438.     DB    62H    ;MANTISSA
  1439.     DB    83H    
  1440.     DB    18H
  1441.     DB    53H
  1442. * RTN. B.39
  1443. * NORMALIZE ANGLE IN RADIANS
  1444. * (HL) MODULO (2PI) TO TMP1
  1445. NRML    PUSH    H    ;SAVE THE ANGLE ADDRESS
  1446.     LXI    D,TWOPI    ;SET UP FOR COMPARE WITH 2*PI
  1447.     CALL    CMPR    ;DO IT
  1448.     POP    H    ;RETRIEVE ADDRESS
  1449.     JC    NRML1    ;AH, IT'S ALREADY LESS THAN 2*PI
  1450.     PUSH    H    ;SAVE THE ANGLE ADDRESS AGAIN
  1451.     LXI    D,TWOPI    ;SET UP FOR DIVIDE BY TWOPI
  1452.     LXI    B,TMP1    ;DESTINATION ADDRESS
  1453.     CALL    DIVER    ;DIVIDE
  1454.     LXI    H,TMP1    ;SET UP FOR INT(TMP1)
  1455.     MOV    D,H
  1456.     MOV    E,L
  1457.     CALL    INTG    ;INT(TMP1) TO TMP1
  1458.     LXI    H,TMP1    ;SET UP FOR TMP1*2*PI
  1459.     LXI    D,TWOPI
  1460.     MOV    B,H
  1461.     MOV    C,L
  1462.     CALL    MULER    ;MULTIPLY
  1463.     POP    H    ;GET BACK THE ANGLE ADDRESS
  1464.     LXI    D,TMP1    ;SET UP FOR ANGLE-(INT(ANGLE/2*PI)*2*PI)
  1465.     MOV    B,D
  1466.     MOV    C,E
  1467.     CALL    SUBER    ;SUBTRACT
  1468.     RET        ;LARGE ANGLE EXIT
  1469. NRML1    LXI    B,TMP1    ;MOVE ANGLE INTO TMP1 AS FLOATING
  1470.     LXI    D,ONE11    ;FLOATING POINT ONE
  1471.     JMP    MULER    ;MULTIPLY IT!
  1472. * CONTSTANTS, ZERO AND ONE
  1473. ONE11    DB    03H
  1474.     DB    00    ;EXPONENT
  1475.     DB    10H
  1476.     DB    00
  1477.     DB    00
  1478.     DB    00H
  1479. ZERO0    DB    02    ;ID BYTE
  1480.     DB    00    ;EXPONENT
  1481.     DB    00    ;MANTISSA
  1482.     DB    00
  1483.     DB    00
  1484.     DB    00
  1485. * RTN. B.40
  1486. * COMPUTE FACTORIAL TERM
  1487. * TMP2 = N
  1488. * TMP3 = N!
  1489. FCTRL    LXI    H,TMP2    ;SET UP TO ADD ONE TO TMP2
  1490.     LXI    D,ONE11
  1491.     MOV    B,H
  1492.     MOV    C,L
  1493.     CALL    ADDER    ;ADD IT
  1494.     LXI    H,TMP2    ;SET UP FOR (TMP2)*(TMP3) TO (TMP3)
  1495.     LXI    D,TMP3
  1496.     MOV    B,D
  1497.     MOV    C,E
  1498.     CALL    MULER    ;MULTIPLY IT
  1499.     RET        ;DONE
  1500. * RTN. B.41
  1501. * TRIG SERIES INITIALIZER
  1502. TRIN    XRA    A    ;GET A ZERO
  1503.     STA    SIGNF    ;CLEAR THE SIGN FLAG
  1504.     LXI    B,6    ;NUMBER OF BYTES
  1505.     PUSH    B    ;SAVE IT
  1506.     LXI    D,TMP5    ;CLEAR TMP5
  1507.     LXI    H,ZERO0
  1508.     CALL    MVDN
  1509.     POP    B    ;SET TMP3, TMP2, TO ONE
  1510.     PUSH    B
  1511.     LXI    H,ONE11
  1512.     PUSH    H
  1513.     LXI    D,TMP2
  1514.     CALL    MVDN
  1515.     POP    H    
  1516.     POP    B
  1517.     LXI    D,TMP3
  1518.     CALL    MVDN
  1519.     LXI    H,TMP1    ;TMP1 SQUARED TO TMP4
  1520.     MOV    D,H
  1521.     MOV    E,L
  1522.     LXI    B,TMP4
  1523.     CALL    MULER
  1524.     RET        ;DONE..
  1525. * RTN. B.43
  1526. * SINE/COSINE SERIES EVALUATION
  1527. * RESULT IS IN TMP6
  1528. SERS    LXI    H,TMP1    ;TMP6=TMP1/TMP3
  1529.     LXI    D,TMP3
  1530.     LXI    B,TMP6
  1531.     CALL    DIVER    ;DIVIDE
  1532.     CALL    TRMN    ;CHECK TO SEE IF WE ARE DONE
  1533.     RC        ;YUP, SO RETURN
  1534.     LXI    H,TMP5    ;TMP5=TMP5+TMP6
  1535.     LXI    D,TMP6
  1536.     MOV    B,H
  1537.     MOV    C,L
  1538.     CALL    ADDER    ;ADD IT
  1539.     CALL    FCTRL    ;COMPUTE TWO FACTORIAL TERMS
  1540.     CALL    FCTRL
  1541.     LXI    H,TMP1    ;TMP1=TMP1*TMP4
  1542.     LXI    D,TMP4
  1543.     MOV    B,H
  1544.     MOV    C,L
  1545.     CALL    MULER    ;MULTIPLY IT
  1546.     JMP    SERS    ;LOOP AND TRY ANOTHER TERM
  1547. * RTN. B.44
  1548. * SINE AND COSINE EVALUATION
  1549. * SINE ENTRANCE PROVIDES SINE
  1550. * COSN ENTRANCE PROVIDES COSINE
  1551. * F(HL) TO (DE)
  1552. SINE    XRA    A    ;CLEAR TMP6
  1553.     STA    TMP6    ;THIS INDICATES SINE
  1554. SICO    PUSH    D    ;SAVE DESTINATION
  1555.     CALL    NRML    ;NORMALIZE ANGLE
  1556.     CALL    TRIN    ;INITIALIZE
  1557.     LDA    TMP6    ;GET SINE/COSINE FLAG
  1558.     ANA    A    ;SET FLAGS
  1559.     JZ    SICO1    ;SKIP IF SINE COMPUTATION
  1560.     LXI    H,ONE11    ;THIS IS COSINE, SO 1 TO TMP1
  1561.     LXI    D,TMP1
  1562.     LXI    B,6
  1563.     CALL    MVDN
  1564.     LXI    H,ZERO0    ;AND ZERO TO TMP2
  1565.     LXI    D,TMP2
  1566.     LXI    B,6
  1567.     CALL    MVDN
  1568. SICO1    CALL    SERS    ;EVALUATE THE SERIES
  1569.     POP    D    ;RESTORE DESTINATION ADDRESS
  1570.     LXI    H,TMP5    ;MOVE FROM TMP5 TO (DE)
  1571.     LXI    B,6
  1572.     CALL    MVDN
  1573.     RET        ;ALL DONE...
  1574. COSN    MVI    A,1    ;SET TMP6 NONZERO
  1575.     STA    TMP6    ;INDICATING THAT THIS IS A COSINE
  1576.     JMP    SICO    ;COMPUTE IT
  1577. * RTN. B.45
  1578. * TANGENT
  1579. * COMPUTED BY TAN(X)=SIN(X)/COS(X)
  1580. TANG    PUSH    D    ;SAVE DESTINATION
  1581.     PUSH    H    ;SAVE SOURCE
  1582.     LXI    D,TMP8    ;TMP8=SIN(HL)
  1583.     CALL    SINE
  1584.     POP    H    ;GET SOURCE AGAIN
  1585.     LXI    D,TMP9    ;TMP9=COS(HL)
  1586.     CALL    COSN
  1587.     LXI    H,TMP8    ;(DE)=TMP8/TMP9
  1588.     LXI    D,TMP9
  1589.     POP    B    ;GET DESTINATION BACK
  1590.     CALL    DIVER    ;DO IT TO IT
  1591.     RET        ;FINI!
  1592. * RTN. B.46
  1593. * ARCTANGENT
  1594. * FOR (HL) > 1.3, USES MACLAURIN SERIES FOR ARCTAN
  1595. * FOR (HL) < 1.3, USES MACLAURIN SERIES FOR ARCSIN,
  1596. * AND THE IDENTITY, ARCTAN(X)=ARCSIN(X/SQU(X*X+1))
  1597. * THIS ENSURES CONVERGENCE WITHIN OUR LIFETIME
  1598. ATAN    PUSH    D    ;SAVE DESTINATION
  1599.     PUSH    H    ;SAVE SOURCE
  1600.     LXI    D,TMP1    ;MOVE (HL) TO TMP1
  1601.     LXI    B,6
  1602.     CALL    MVDN    ;MOVE IT
  1603.     MOV    H,D    ;COMPUTE TMP4=TMP1*TMP1
  1604.     MOV    L,E
  1605.     LXI    B,TMP4
  1606.     CALL    MULER    ;MULTIPLY
  1607.     LXI    H,TMP4    ;COMPARE TMP4 AND 1.69
  1608.     LXI    D,CONS1
  1609.     CALL    CMPR    ;COMPARE
  1610.     POP    H    ;RESTORE SOURCE ADDRESS
  1611.     JC    ATAN2    ;TOO SMALL, SO USE ARCSIN SERIES
  1612.     LXI    H,CONS2    ;MOVE PI/2 TO TMP5
  1613.     LXI    D,TMP5
  1614.     LXI    B,6
  1615.     CALL    MVDN
  1616.     LXI    H,ONE11    ;MOVE ONE INTO TMP2
  1617.     LXI    D,TMP2
  1618.     LXI    B,6
  1619.     CALL    MVDN
  1620.     MVI    A,80H    ;SET SIGN CHANGE FLAG TO 80H
  1621.     STA    SIGNF
  1622.     LDA    TMP1    ;MAKE MANTISSA SIGN OF TMP5 SAME
  1623.     ANI    80H    ;AS SIGN OF TMP1
  1624.     MOV    B,A    ;SAVE SIGN OF TMP1 IN B
  1625.     LXI    H,TMP5    ;ADDRESS OF ID BYTE
  1626.     MOV    A,M    ;GET IT
  1627.     ANI    7FH    ;STRIP ALL BUT SIGN OF MANTISSA
  1628.     ORA    B    ;SET IN SIGN OF TMP1
  1629.     MOV    M,A    ;STICK IT BACK
  1630.     LXI    H,ONE11    ;TMP1=1/TMP1
  1631.     PUSH    H    ;SAVE THIS ADDRESS
  1632.     LXI    D,TMP1
  1633.     MOV    B,D
  1634.     MOV    C,E
  1635.     CALL    DIVER    ;DIVIDE IT
  1636.     POP    H    ;GET ONE.. ADDRESS BACK
  1637.     LXI    D,TMP4    ;TMP4=1/TMP4
  1638.     MOV    B,D
  1639.     MOV    C,E
  1640.     CALL    DIVER    ;DIVIDE IT
  1641. ATAN1    LXI    H,TMP1    ;TMP6=TMP1/TMP2
  1642.     LXI    D,TMP2
  1643.     LXI    B,TMP6
  1644.     CALL    DIVER    ;DIVIDE
  1645.     CALL    TRMN    ;CHECK FOR DONENESS
  1646.     JC    ATAN3    ;OH, MY, ALL DONE
  1647.     LXI    H,TMP2    ;TMP2=TMP2+2
  1648.     MOV    B,H
  1649.     MOV    C,L
  1650.     LXI    D,TWO22
  1651.     CALL    ADDER    ;ADD
  1652.     LXI    H,TMP1    ;TMP1=TMP1*TMP4
  1653.     MOV    B,H
  1654.     MOV    C,L
  1655.     LXI    D,TMP4
  1656.     CALL    MULER    ;MULTIPLY
  1657.     LXI    H,TMP5    ;TMP5=TMP5+TMP6
  1658.     MOV    B,H
  1659.     MOV    C,L
  1660.     LXI    D,TMP6
  1661.     CALL    ADDER    ;ADD
  1662.     JMP    ATAN1    ;LOOP FOR ANOTHER TERM
  1663. TWO22    DB    03    ;CONSTANT OF 2
  1664.     DB    00    ;EXPONENT
  1665.     DB    20H    ;MANTISSA
  1666.     DB    00
  1667.     DB    00    
  1668.     DB    00
  1669. CONS1    DB    03    ;CONSTANT, 1.69
  1670.     DB    00    ;EXPONENT
  1671.     DB    16H    ;MANTISSA
  1672.     DB    90H
  1673.     DB    00
  1674.     DB    00
  1675. CONS2    DB    03    ;ID BYTE FOR PI/2
  1676.     DB    00    ;EXPONENT
  1677.     DB    15H    ;MANTISSA
  1678.     DB    70H
  1679.     DB    79H
  1680.     DB    63H
  1681. ATAN2    PUSH    H    ;SAVE SOURCE ADDRESS
  1682.     LXI    H,ONE11    ;TMP10=TMP4+1
  1683.     LXI    D,TMP4
  1684.     LXI    B,TMP10
  1685.     CALL    ADDER    ;ADD
  1686.     LXI    H,TMP10    ;TMP10=SQR(TMP10)
  1687.     MOV    D,H
  1688.     MOV    E,L
  1689.     CALL    SQUR    ;COMPUTE SQUARE ROOT
  1690.     POP    H    ;RESTORE SOURCE ADDRESS
  1691.     LXI    D,TMP10    ;TMP1=(HL)/TMP10
  1692.     LXI    B,TMP1
  1693.     CALL    DIVER    ;DIVIDE IT
  1694.     LXI    H,TMP1    ;TMP4=TMP1*TMP1
  1695.     MOV    D,H
  1696.     MOV    E,L
  1697.     LXI    B,TMP4
  1698.     CALL    MULER    ;MULTIPLY
  1699.     LXI    H,ONE11    ;TMP3=1
  1700.     LXI    D,TMP3
  1701.     LXI    B,6
  1702.     CALL    MVDN
  1703.     LXI    D,TMP9    ;TMP9=1
  1704.     CALL    MVDN
  1705.     LXI    H,ZERO0    ;TMP5=0
  1706.     LXI    D,TMP5
  1707.     CALL    MVDN
  1708.     LXI    D,TMP2    ;TMP2=0
  1709.     CALL    MVDN
  1710. ATAN4    LXI    H,TMP9    ;TMP7=TMP9*TMP1
  1711.     LXI    D,TMP1
  1712.     LXI    B,TMP7
  1713.     CALL    MULER    ;MULTIPLY
  1714.     LXI    H,ONE11    ;TMP8=TMP2+1
  1715.     LXI    D,TMP2
  1716.     LXI    B,TMP8
  1717.     CALL    ADDER    ;ADD
  1718.     LXI    H,TMP7    ;TMP7=TMP7/TMP8
  1719.     LXI    D,TMP8
  1720.     MOV    B,H
  1721.     MOV    C,L
  1722.     CALL    DIVER    ;DIVIDE
  1723.     LXI    H,TMP7    ;TMP6=TMP7/TMP3
  1724.     LXI    D,TMP3
  1725.     LXI    B,TMP6
  1726.     CALL    DIVER    ;DIVIDE
  1727.     CALL    TRMN1    ;CHECK FOR DONENESS
  1728.     JC    ATAN3    ;OK, WE'RE DONE
  1729.     LXI    H,TMP5    ;TMP5=TMP5+TMP6
  1730.     LXI    D,TMP6
  1731.     MOV    B,H
  1732.     MOV    C,L
  1733.     CALL    ADDER    ;ADD
  1734.     LXI    H,TMP2    ;TMP2=TMP2+1
  1735.     LXI    D,ONE11    
  1736.     MOV    B,H
  1737.     MOV    C,L
  1738.     CALL    ADDER    ;ADD
  1739.     LXI    H,TMP9    ;TMP9=TMP9*TMP2
  1740.     LXI    D,TMP2
  1741.     MOV    B,H
  1742.     MOV    C,L
  1743.     CALL    MULER    ;MULTIPLY
  1744.     CALL    FCTRL    ;COMPUTE ANOTHER FACTORIAL TERM
  1745.     LXI    H,TMP1    ;TMP1=TMP1*TMP4
  1746.     LXI    D,TMP4
  1747.     MOV    B,H
  1748.     MOV    C,L
  1749.     CALL    MULER    ;MULTIPLY
  1750.     JMP    ATAN4    ;LOOP FOR ANOTHER TERM
  1751. ATAN3    POP    D    ;GET DESTINATION ADDRESS
  1752.     LXI    H,TMP5    ;MOVE TMP5 THERE
  1753.     LXI    B,6
  1754.     CALL    MVDN
  1755.     RET        ;DONE AT LAST!!
  1756. * RTN. B.47
  1757. * CONVERT NUMBER TO TWO BYTE BINARY
  1758. * (HL) TO HL
  1759. BCDB    LXI    D,TMP9    ;CONVERT TO INTEGER IN TMP9
  1760.     CALL    INTG
  1761.     LXI    H,TMP9    ;COMPARE WITH 32767
  1762.     LXI    D,C2767
  1763.     CALL    CMPR
  1764.     JNC    BCDB2    ;JUMP IF NUMBER TOO LARGE TO CONVERT
  1765.     LXI    H,0    ;CLEAR HL
  1766.     LXI    B,TMP9+3    ;INITIALIZE FOR CONVERSION LOOP
  1767.     LDAX    B    ;GET A DIGIT
  1768.     MOV    L,A    ;TO L
  1769.     INX    B    ;GET NEXT DIGIT ADDRESS
  1770.     XRA    A    ;CLEAR FLAGS AND A
  1771. BCDB1    PUSH    PSW    ;SAVE FLAGS
  1772.     PUSH    B    ;SAVE INDEX
  1773.     DAD    H    ;HL=HL*100 (BY TOM GALLANT)
  1774.     DAD    H    ;GENERATE HL*4
  1775.     MOV    D,H    ;TO DE
  1776.     MOV    E,L
  1777.     DAD    H    ;GENERATE HL*32
  1778.     DAD    H
  1779.     DAD    H
  1780.     MOV    B,H    ;TO BC
  1781.     MOV    C,L
  1782.     DAD    H    ;GENERATE HL*64
  1783.     DAD    D
  1784.     DAD    B
  1785.     POP    B    ;RESTORE INDEX
  1786.     LDAX    B    ;GET NEXT DIGIT
  1787.     CALL    BCDBN    ;CONVERT TO BINARY
  1788.     MOV    E,A    ;TO DE
  1789.     MVI    D,0    ;CLEAR D
  1790.     DAD    D    ;ADD TO PARTIAL SUM
  1791.     INX    B    ;UPDATE INDEX
  1792.     POP    PSW    ;GET FLAGS BACK
  1793.     CMC        ;TEST LOOP COUNTER
  1794.     JC    BCDB1    ;MORE TO GO!
  1795.     LDA    TMP9    ;CHECK SIGN BIT
  1796.     ANA    A    ;SET FLAGS
  1797.     RP        ;ALL'S OK
  1798.     XCHG
  1799.     LXI    H,0    ;GET THE COMPLEMENT
  1800.     CALL    SUB16
  1801.     RET        ;DONE%
  1802. * RTN. B.48
  1803. * CONVERT BINARY TO NUMBER
  1804. * HL TO (DE)
  1805. BBCD    MOV    A,H    ;CHECK FOR A NEGATIVE NUMBER
  1806.     ANI    80H    ;SET FLAGS AND STRIP OTHER BITS
  1807.     MOV    B,A    ;SIGN BIT TO B FOR PATTERN
  1808.     JZ    BBBCD    ;POSITIVE NUMBER
  1809.     MOV    A,H    ;COMPLEMENT HL
  1810.     CMA
  1811.     MOV    H,A
  1812.     MOV    A,L
  1813.     CMA
  1814.     MOV    L,A
  1815.     INX    H    ;CORRECT FOR 2'S COMPLEMENT
  1816. BBBCD    MVI    A,2    ;SET ID BYTE
  1817.     ORA    B    ;SET IN THE SIGN BIT
  1818.     STAX    D
  1819.     XCHG        ;SET UP TO ZERO OUT NUMBER
  1820.     INX    H    ;GET NEXT BYTE
  1821.     MVI    A,5    ;SET UP FOR 5 BYTES
  1822.     CALL    ZERO    ;ZERO OUT FIVE BYTES
  1823.     DCX    H    ;CORRECT THE INDEX
  1824.     MVI    A,3    ;NUMBER OF EXECUTIONS FOR CONVERSION LOOP
  1825.     XCHG        ;PUT BINARY BACK IN HL
  1826.     MOV    B,D    ;PUT DESTINATION IN BC
  1827.     MOV    C,E
  1828. BBCD1    PUSH    PSW    ;SAVE THE COUNT
  1829.     PUSH    B    ;SAVE INDEX
  1830.     LXI    B,0    ;CLEAR COUNTER
  1831.     LXI    D,100    ;SET SUBTRACTOR
  1832. BBCDA    CALL    CMP16    ;CHECK FOR IT FITTING
  1833.     JC    BBCDB    ;NOPE
  1834.     CALL    SUB16    ;YUP
  1835.     INX    B    ;UPDATE THE QUOTIENT
  1836.     JMP    BBCDA
  1837. BBCDB    MOV    A,L    ;GET REMAINDER TO A
  1838.     MOV    L,C    ;MOVE QUOTIENT TO HL
  1839.     MOV    H,B
  1840.     CALL    STNMP
  1841.     POP    B    ;RESTORE INDEX
  1842.     STAX    B    ;STORE IT AWAY
  1843.     DCX    B    ;UPDATE INDEX
  1844.     POP    PSW    ;GET THE COUNT BACK TO A
  1845.     DCR    A    ;CHECK THE COUNT
  1846.     JNZ    BBCD1    ;LOOP IF MORE TO DO
  1847.     RET        ;DONE$$$$
  1848. BCDB2    MVI    B,5    ;GET ERROR TYPE
  1849.     JMP    ERROR    ;ERROR ESCAPE
  1850. * I/O MODULE
  1851. * RTN. C.1
  1852. * FIND MODE ENTRY, GET CHANNEL ADDRESS AND TERMINAL
  1853. * DELIMITERS
  1854. * IN: A = MODE TO LOOK FOR
  1855. *  BC = CHANNEL NUMBER TO START LOOKING WITH
  1856. * OUT: IF Z = 0 THEN NO FIND
  1857. *  IF Z = 1, THEN FIND AND;
  1858. *  HL = CHANNEL ADDRESS
  1859. *  DE = ADDRESS OF WIDTH/POSITION/RUBOUT CODE
  1860. *  BC = NEXT CHANNEL NUMBER
  1861. MFND    LXI    H,MODES-1     ;COMPUTE STARTING ADDRESS
  1862.     DAD    B
  1863.     MOV    D,A    ;MASK TO D
  1864. MFND3    MOV    A,C    ;BC=11?
  1865.     CPI    11
  1866.     JZ    MFND1    ;YUP
  1867.     MOV    A,M    ;GET A BYTE
  1868.     ANA    D    ;CHECK AGAINST MASK
  1869.     JNZ    MFND2    ;GOT ONE
  1870.     INX    B    ;SET UP FOR NEXT ONE
  1871.     INX    H
  1872.     JMP    MFND3    ;GO GET IT
  1873. MFND2    MOV    L,C    ;HL=BC
  1874.     MOV    H,B
  1875.     DAD    H    ;TIMES TWO
  1876.     PUSH    H    ;SAVE TIMES TWO
  1877.     LXI    D,CHANL-2    ;GET BEGINNING OF CHANNEL TABLE - OFFSET
  1878.     DAD    D    ;COMPUTE ENTRY ADDRESS
  1879.     MOV    E,M    ;PUT THE ENTRY IN DE
  1880.     INX    H    ;NEXT ONE
  1881.     MOV    D,M
  1882.     POP    H    ;GET BACK TIMES TWO
  1883.     DAD    B    ;MAKE IT TIMES THREE
  1884.     PUSH    D    ;SAVE CHANNEL ADDRESS
  1885.     LXI    D,TRMNL-3    ;GET WIDTH/POSITION/RUBOUT START-OFFSET
  1886.     DAD    D    ;COMPUTE ENTRY ADDRESS
  1887.     POP    D    ;RESTORE CHANNEL ADDRESS
  1888.     XCHG        ;SWAP
  1889.     INX    B    ;GET NEXT ITEM NUMBER
  1890.     XRA    A    ;SET THE ZERO FLAG
  1891.     RET        ;DONE..
  1892.     POP    H    ;CLEAN UP STACK
  1893.     RET        ;LEAVE..
  1894. MFND1    ORI    100    ;RESTORE A
  1895.     ORI    1    ;CLEAR THE ZERO FLAG
  1896.     RET        ;DONE......
  1897. * RTN. C.2
  1898. * CONTROL C SCANNER
  1899. * CALLS THE KEYBOARD ROUTINE WITH ZERO SET FOR 
  1900. * A CHECK FOR CONTROL C PUSHED.
  1901. * OUT: ZERO SET IF CONTROL C PUSHED
  1902. CONT    XRA    A    ;SET THE ZERO FLAG
  1903. CONT1    PUSH    PSW    ;SAVE IT
  1904.     MVI    A,1    ;GET MODE KEYBOARD
  1905.     PUSH    B    ;SAVE BC
  1906.     LXI    B,1    ;START WITH CHANNEL ONE
  1907.     CALL    MFND    ;FIND THE KEYBOARD CHANNEL
  1908.     POP    B    ;RESTORE BC
  1909.     POP    PSW    ;GET THE FLAG BACK
  1910.     PCHL        ;GO TO THE KEYBOARD ROUTINE
  1911. LINK2    LINK    A:TBASICA3
  1912.