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 / TBASICA1.ASM < prev    next >
Assembly Source File  |  1984-04-29  |  26KB  |  1,025 lines

  1. * TARBELL BASIC
  2. * COPYRIGHT (C) 1978 TARBELL ELECTRONICS
  3. YES    EQU    0FFFFH
  4. NO    EQU    NOT YES
  5. CASSETTE    EQU    YES
  6. DISK    EQU    NO
  7.     ORG    500H
  8. * DESIGNED BY TOM DILATUSH AND JIM BARNICK OF
  9. * REAL TIME MICROSYSTEMS, CHULA VISTA, CALIFORNIA
  10. * CODED BY TOM DILATUSH, WITH A LITTLE HELP
  11. * FROM TOM GALLANT, BOB BROWN, AND SAM SINGER
  12. *
  13. * COMMON MODULE
  14. * TESTED 17 NOVEMBER 1977
  15. * OBJECT OCCUPIES 316 BYTES
  16. START    JMP    STARS
  17.     DW    CHANL    ;POINTER TO CHANL
  18.     DW    TRMNL    ;POINTER TO TRMNL
  19.     DW    SSSS    ;POINTER TO SSSS
  20.     DW    CNVRA    ;POINTER TO CNVRA
  21.     DW    FPRAA+6    ;POINTER TO USER ADDRESS
  22.     DW    MODES    ;POINTER TO MODES TABLE.
  23.     DW    FSRC    ;PTR TO FIRST SOURCE BYTE.
  24.     DW    ESRC    ;PTR TO 1ST BYTE AFTER SOURCE.
  25.     DW    ERROR    ;POINTER TO ERROR ROUTINE
  26.     DW    TSCN    ;POINTS TO TOKEN JUST SCANNED
  27.     DW    NSCN    ;POINTS TO TOKEN TO BE SCANNED NEXT
  28.     DW    CHCK    ;POINTS TO CHECKSUM ROUTINE
  29.     DW    INFL    ;INTEGER TO FLOATING, (HL) TO (DE)
  30.     DW    FLIN    ;FLOATING TO INTEGER, (HL) TO (DE)
  31.     DW    STNM    ;STRING AT (HL) TO NUMBER AT (DE)
  32.     DW    NMST    ;NUMBER AT (HL) TO STRING AT (DE)
  33.     DW    CMPR    ;ZERO AND CARRY SET AS FOR (HL)-(DE)
  34.     DW    SINE    ;SINE(HL) TO (DE)
  35.     DW    SICO    ;COSINE(HL) TO (DE)
  36.     DW    TANG    ;TANGENT(HL) TO (DE)
  37.     DW    ATAN    ;ARCTANGENT(HL) TO (DE)
  38.     DW    BCDB    ;NUMBER AT (HL) TO BINARY IN HL
  39.     DW    BBCD    ;BINARY NUMBER IN HL TO NUMBER AT (DE)
  40.     DW    ETOX    ;E TO THE (HL) POWER TO (DE)
  41.     DW    LOGX    ;LOG BASE E (HL) TO (DE)
  42.     DW    SQUR    ;(HL) TO 1/2 TO (DE)
  43.     DW    PWRS    ;(HL) TO THE (DE) POWER TO (BC)
  44.     DW    ADDER    ;(HL)+(DE) TO (BC)
  45.     DW    SUBER    ;(HL)-(DE) TO (BC)
  46.     DW    MULER    ;(HL)*(DE) TO (BC)
  47.     DW    DIVER    ;(HL)/(DE) TO (BC)
  48. STARS    LXI    SP,STACK+100     ;INITIALIZE THE STACK
  49.     MVI    A,0C9H
  50.     STA    IOST+2
  51.     CALL    CHCK    ;SET INTEGRITY FLAG
  52.     STA    CHECK
  53.     LDA    SRFLG    ;CHECK FOR PREVIOUS INITIALIZATION
  54.     ANA    A
  55.     JNZ    INTR    ;GOTO TO NORMAL INITIALIZATION
  56.     XRA    A    ;INITIALIZE EDIT FLAGS
  57.     STA    MERR    ;INITIALIZE THE MATH ERROR FLAG
  58.     LXI    H,0
  59.     SHLD    DMPMM
  60.     STA    EDITM
  61.     CALL    INIO    ;INITIALIZE THE I/O ROUTINES
  62.     LHLD    SMEN    ;SEE IF A MONITOR NEEDS TO BE LOADED
  63.     MOV    A,H
  64.     ORA    L
  65.     JZ    S0000    ;NOPE
  66.     LHLD    SMST    ;GET FIRST ADDRESS OF MONITOR
  67. S0001    PUSH    H    ;SAVE ADDRESS
  68.     CALL    CAIN    ;GET A BYTE FROM CASSETTE
  69.     POP    H    ;GET ADDRESS BACK
  70.     MOV    M,A    ;STUFF IT IN
  71.     XCHG        ;TO DE
  72.     LHLD    SMEN    ;CHECK FOR DONENESS
  73.     CALL    CMP16
  74.     XCHG
  75.     JNZ    S0001    ;NOPE, SO LOOP FOR ANOTHER BYTE
  76. S0000    LXI    H,BEGIN    ;DUMP THE GREETING
  77.     CALL    MSGER
  78.     MVI    A,0FFH    ;SET SRFLG
  79.     STA    SRFLG
  80.     JMP    INTR    ;CONTINUE WITH INITIALIZATION
  81. BEGIN    DB    0DH,'TARBELL '
  82.  
  83.     IF    DISK
  84.     DB    'DISK'
  85.     ENDIF
  86.  
  87.     IF    CASSETTE
  88.     DB    'CASSETTE'
  89.     ENDIF
  90.  
  91.     DB    ' BASIC',0DH
  92.     DB    'BY REAL TIME MICROSYSTEMS, CHULA VISTA, CA'
  93.     DB    0DH
  94.     DB    'FOR TARBELL ELECTRONICS, CARSON, CA',0DH
  95.     DB    'RELEASE 5.2  AUGUST 16, 1978',8DH
  96. * NOTE: FIRST DIGIT OF RELEASE NUMBER IS RTM'S.
  97. *    SECOND DIGIT IS TARBELL ELECTRONICS'.
  98. *    NEW COMPANIES SHOULD ADD . AND NUMBER.
  99. *
  100. * RTN A.1
  101. * 16 BIT SUBTRACT
  102. * HL=HL-DE
  103. SUB16    MOV    A,L
  104.     SUB    E
  105.     MOV    L,A    ;BACK TO WHENCE IT CAME
  106.     MOV    A,H    ;SUBTRACT MSB'S
  107.     SBB    D    ;WITH THE CARRY (BORROW)
  108.     MOV    H,A    ;AND BACK
  109.     CMC        ;REVERSE THE CARRY FLAG
  110.     RET        ;ALL DONE
  111. * RTN A.2
  112. * 16 BIT COMPARE
  113. * FLAGS ARE SET AS FOR HL-DE, WITHOUT AFFECTING
  114. * THE REGISTERS. A IS CHANGED.
  115. * ONLY CARRY AND ZERO ARE CORRECTLY SET
  116. CMP16    MOV    A,H    ;TEST MSB'S
  117.     SUB    D
  118.     RNZ        ;NOT THE SAME
  119.     MOV    A,L    ;TEST LSB'S
  120.     SUB    E
  121.     RET        ;DONE.
  122. * RTN A.3
  123. * 8 BY 8 MULTIPLY
  124. * DE=D*E, NO OTHER REGISTERS DISTURBED
  125. MULT    PUSH    H
  126.     PUSH    PSW     ;SAVE REGISTERS
  127.     MOV    H,D    ;SET UP MULTIPLIERS
  128.     MVI    L,0    ;CLEAR SOME
  129.     MOV    D,L
  130.     DAD    H    ;SHIFT AND ADD (S/A) 1
  131.     JNC    MULT2    ;NO ADD
  132.     DAD    D    ;ADD
  133. MULT2    DAD    H    ;S/A 2
  134.     JNC    MULT3
  135.     DAD    D
  136. MULT3    DAD    H    ;S/A 3
  137.     JNC    MULT4
  138.     DAD    D
  139. MULT4    DAD    H    ;S/A 4
  140.     JNC    MULT5
  141.     DAD    D
  142. MULT5    DAD    H    ;S/A 5
  143.     JNC    MULT6
  144.     DAD    D
  145. MULT6    DAD    H    ;S/A 6
  146.     JNC    MULT7
  147.     DAD    D
  148. MULT7    DAD    H    ;S/A 7
  149.     JNC    MULT8
  150.     DAD    D
  151. MULT8    DAD    H    ;S/A 8
  152.     JNC    MULT9    ;DONE
  153.     DAD    D
  154. MULT9    POP    PSW    ;RESTORE REGISTERS
  155.     XCHG        ;PRODUCT TO DE
  156.     POP    H
  157.     RET        ;DONE.
  158. * RTN. A.4
  159. * FAST MULTIPLY BY 6
  160. * HL=HL*6
  161. * NO OTHER REGISTERS DISTURBED
  162. * CARRY SET IF OVERFLOW
  163. FSTML    PUSH    D    ;SAVE DE
  164.     DAD    H    ;MULTIPLY HL BY 2
  165.     MOV    D,H    ;SEND IT TO DE
  166.     MOV    E,L
  167.     DAD    H    ;MULTIPLY HL BY 2 
  168.     DAD    D    ;6X=4X+2X
  169.     POP    D    ;RESTORE DE
  170.     RET        ;GO AWAY
  171. * RTN. A.5
  172. * MOVE BLOCK DOWN
  173. * (HL) TO (DE), BC TIMES
  174. * NO REGISTERS DISTURBED
  175. MVDN    PUSH    PSW    ;SAVE THE WORLD
  176.     PUSH    B
  177.     PUSH    D
  178.     PUSH    H
  179. MVDN1    MOV    A,M    ;GET DATA
  180.     STAX    D    ;STORE IT IN NEW LOCATION
  181.     INX    H    ;UPDATE INDEXES
  182.     INX    D
  183.     DCX    B    ;UPDATE BYTE COUNTER
  184.     MOV    A,B    ;BC = 0?
  185.     ORA    C
  186.     JNZ    MVDN1    ;JUMP IF MORE BYTES TO MOVE
  187.     POP    H    ;RESTORE THE WORLD TO IT'S FORMER STATE
  188.     POP    D
  189.     POP    B
  190.     POP    PSW
  191.     RET        ;ALL DONE
  192. * RTN. A.6 
  193. * MOVE BLOCK UP
  194. * (HL) TO (DE), BC TIMES
  195. * NO REGISTERS DISTURBED
  196. MVUP    PUSH    PSW    ;SAVE THE WORLD
  197.     PUSH    B
  198.     PUSH    D
  199.     PUSH    H
  200.     DAD    B    ;CHANGE INDEXES TO LAST BYTE+1
  201.     XCHG        ;GET DE TO HL
  202.     DAD    B    ;CHANGE DE
  203.     XCHG        ;BACK TO NORMAL
  204. MVUP1    DCX    H    ;UPDATE INDEXES
  205.     DCX    D
  206.     DCX    B    ;UPDATE THE CHARACTER COUNTER
  207.     MOV    A,M    ;GET THE DATA
  208.     STAX    D    ;STORE IT TO NEW LOCATION
  209.     MOV    A,B    ;IS BC=0?
  210.     ORA    C
  211.     JNZ    MVUP1    ;MORE DATA TO MOVE
  212.     POP    H    ;RESTORE THE WORLD
  213.     POP    D
  214.     POP    B
  215.     POP    PSW
  216.     RET        ;DONE
  217. * RTN. A.7
  218. * MOVE DATA BLOCK
  219. * WILL MOVE OVERLAPPING BLOCKS UP OR DOWN WITHOUT
  220. * ERRORS
  221. * (HL) TO (DE), BC TIMES
  222. * NO REGISTERS ARE DISTURBED
  223. MOVE    CALL    CMP16    ;SEE WHETHER MOVING DATA UP OR DOWN
  224.     CC    MVUP    ;CARRY SET SO WE'RE GOING UP
  225.     CNC    MVDN    ;CARRY CLEAR SO WE'RE GOING DOWN
  226.     RET        ;DONE
  227. * RTN. A.8
  228. * STRING COMPARE
  229. * FIRST BYTE OF TWO STRINGS MUST BE ADDRESSED
  230. * BY HL AND DE.
  231. * IF (HL)=(DE), THE ZERO FLAG IS SET
  232. * IF (DE)<(HL), THE CARRY FLAG IS SET
  233. * REGISTER A IS DISTURBED
  234. * LAST CHARACTER OF STRINGS MUST HAVE 2 TO THE 7 SET
  235. STRNG    PUSH    B    ;SAVE THE WORLD
  236.     PUSH    D
  237.     PUSH    H
  238.     MVI    C,0    ;CLEAR END FLAG
  239. STRN1    MOV    A,M    ;GET A CHARACTER
  240.     ANA    A    ;CHECK FOR LAST ONE
  241.     JP    STRN2    ;NOT THE LAST ONE
  242.     INR    C    ;SET END FLAG
  243.     ANI    7FH    ;STRIP UPPER BIT
  244. STRN2    CALL    STRN10    ;CONVERT TO UPPER CASE
  245.     MOV    B,A    ;CHARACTER TO B
  246.     LDAX    D    ;GET CHARACTER FROM OTHER STRING
  247.     ANA    A    ;CHECK FOR LAST ONE
  248.     JP    STRN3    ;NOT THE LAST ONE
  249.     INR    C    ;CHECK IF BOTH STRINGS END HERE
  250.     DCR    C
  251.     JNZ    STRN6    ;YES, BOTH END HERE
  252.     DCR    A    ;CORRECT A IF ONLY ONE ENDING HERE
  253. STRN6    INR    C    ;SET END FLAG
  254.     ANI    7FH    ;STRIP UPPER BIT
  255. STRN3    CALL    STRN10
  256.     SUB    B    ;COMPARE THE TWO CHARACTERS
  257.     INX    D    ;UPDATE INDEXES
  258.     INX    H
  259.     PUSH    PSW    ;SAVE COMPARE RESULT
  260.     DCR    C    ;CHECK IF END OF STRING OCCURED
  261.     INR    C
  262.     JNZ    STRN4    ;END OCCURED, SO LEAVE
  263.     POP    PSW    ;GET RESULT BACK
  264.     JZ    STRN1    ;TRY NEXT CHARACTER
  265. STRN5    POP    H    ;RESTORE THE WORLD
  266.     POP    D
  267.     POP    B
  268.     RET        ;PHEW, DONE!
  269. STRN4    DCR    C    ;CHECK TO SEE IF BOTH STRINGS ENDED HERE
  270.     DCR    C
  271.     JZ    STRN8    ;YUP, BOTH ENDED HERE
  272.     POP    PSW    ;GET RESULT BACK
  273.     DCR    C    ;CLEAR ZERO FLAG (DIFFERENT LENGTHS CAN'T
  274. * BE EQUAL
  275.     PUSH    PSW    ;SAVE RESULT AGAIN
  276. STRN8    POP    PSW    ;RESTORE RESULT
  277.     JMP    STRN5    ;LEAVE
  278. STRN10    CPI    7BH    ;CHECK FOR LOWER CASE
  279.     RNC        ;NOPE
  280.     CPI    61H
  281.     RC
  282.     ANI    5FH
  283.     RET
  284. * RTN. A.9
  285. * STRING SEARCH
  286. * SEARCHES A TABLE STARTING AT (DE) OF BC ITEMS
  287. * FOR THE FIRST OCCURENCE OF A STRING (HL)
  288. * ON RETURN, IF ZERO SET, A FIND WAS MADE, AND
  289. * BC = ITEM NUMBER, DE = FIRST ADDRESS OF
  290. * MATCHING STRING
  291. * IF ZERO IS CLEARED, NO FIND WAS MADE, AND
  292. * BC = NEXT ITEM NUMBER, DE = NEXT ADDRESS
  293. * AFTER THE TABLE.
  294. STSRH    PUSH    B    ;SAVE NUMBER OF ITEMS
  295. STSRC    CALL    STRNG    ;COMPARE STRINGS
  296.     JZ    STSC1    ;AH, FOUND IT
  297. * ADVANCE TILL NEXT STRING
  298. STSC2    LDAX    D    ;GET A CHARACTER
  299.     ANA    A    ;SET FLAGS
  300.     INX    D    ;UPDATE COUNTER
  301.     JP    STSC2    ;NOT LAST CHARACTER YET
  302.     DCX    B    ;UPDATE ITEM COUNTER
  303.     MOV    A,B    ;LAST ITEM?
  304.     ORA    C
  305.     DCR    A    ;MAKE ZERO FLAG CLEAR IF ZERO
  306.     JM    STSC1    ;YUP, SO NO FINDS
  307.     JP    STSRC    ;LOOP FOR NEXT STRING
  308. STSC1    XTHL        ;GET NUMBER OF ITEMS AND SAVE HL
  309.     PUSH    D    ;SAVE DE
  310.     MOV    D,B    ;BC TO DE
  311.     MOV    E,C
  312.     PUSH    PSW    ;SAVE FLAGS
  313.     CALL    SUB16    ;COMPUTE ITEM NUMBER OF FIND
  314.     POP    PSW    ;RESTORE FLAGS
  315.     INX    H    ;CORRECT TO MAKE FIRST ITEM #1
  316.     POP    D    ;GET BACK DE
  317.     XTHL        ;GET BACK HL, SAVING COMPUTED ITEM NUMBER
  318.     POP    B    ;GET BACK ITEM NUMBER
  319.     RET        ;ALL DONE.
  320. * RTN. A.10 
  321. * COUNT CHARACTERS IN STRING
  322. * CHARACTERS IN STRING (HL) TO DE
  323. * A,B,C,H,L NOT DISTURBED
  324. COUNT    PUSH    PSW    ;SAVE REGISTERS
  325.     PUSH    H
  326.     LXI    D,0    ;CLEAR DE
  327.     XRA    A    ;CLEAR FLAGS
  328. CNT1    INX    D    ;UPDATE COUNTER
  329.     ORA    M    ;SET FLAGS
  330.     INX    H    ;UPDATE INDEX
  331.     JP    CNT1    ;LOOP IF NOT END YET
  332.     POP    H    ;RESTORE REGISTERS
  333.     POP    PSW
  334.     RET        ;FINI
  335. * RTN. A.11
  336. * BINARY DIVIDE 16/8 TO 8 WITH REMAINDER, ROUNDED AND
  337. * UNROUNDED QUOTIENTS
  338. * L = HL/E, UNROUNDED, H=REMAINDER
  339. * DE = HL/E, ROUNDED
  340. * B,C NOT DISTURBED
  341. * CARRY CLEARED IF OVERFLOW
  342. DIV    PUSH    B    ;SAVE REGISTERS
  343.     MOV    A,H    ;CHECK FOR OVERFLOW
  344.     SUB    E
  345.     JNC    DIV6    ;OH,DEAR, OVERFLOW
  346.     MVI    B,0    ;INITIALIZE QUOTIENT REGISTER
  347.     MVI    C,8    ;INITIALIZE SHIFT COUNTER
  348. DIV3    DAD    H    ;SHIFT HL LEFT
  349.     JC    DIV1    ;JUMP IF A BIT FELL OFF
  350.     MOV    A,H    ;TEST SUBTRACT
  351.     SUB    E    ;WILL IT FIT?
  352.     JC    DIV2    ;NOPE, TOO SMALL
  353. DIV1    MOV    A,H    ;PERFORM SUBTRACTION FOR REAL
  354.     SUB    E
  355.     MOV    H,A    ;STICK IT BACK
  356.     STC        ;SHIFT A 'ONE' INTO QUOTIENT
  357. DIV5    MOV    A,B    ;SET UP TO SHIFT CARRY INTO QUOTIENT
  358.     RAL        ;SHIFT
  359.     MOV    B,A    ;STICK IT BACK
  360.     DCR    C    ;UPDATE SHIFT COUNTER
  361.     JNZ    DIV3    ;LOOP IF MORE SHIFTS TO DO
  362.     MOV    A,E    ;ROUND QUOTIENT
  363.     MVI    D,0    ;CLEAR D
  364.     ANA    A    ;CLEAR CARRY
  365.     RAR        ;DIVIDE BY TWO
  366.     MOV    E,B    ;UNROUNDED QUOTIENT TO E
  367.     CMP    H    ;REMAINDER*2>=DIVISOR?
  368.     JNC    DIV4    ;NOPE
  369.     INX    D    ;YES, SO INCREMENT
  370. DIV4    STC        ;SET FLAG FOR NO OVERFLOW
  371. DIV6    MOV    L,B    ;SEND UNROUNDED QUOTIENT TO L
  372.     POP    B    ;RESTORE REGISTERS
  373.     RET        ;GO AWAY
  374. DIV2    ANA    A    ;CLEAR CARRY TO SHIFT A 0
  375.     JMP    DIV5    ;SHIFT IT IN
  376. * RTN. A.12
  377. * 8 BIT SEARCH
  378. * SEARCHES FROM HL FOR BC BYTES, LOOKING FOR A
  379. * ZERO SET IF FIND
  380. * A,D,E NOT DISTURBED
  381. * BC = ITEM NUMBER
  382. * HL = ADDRESS OF FIND
  383. SRC8    PUSH    B    ;SAVE REGISTERS
  384. SRC82    CMP    M    ;COMPARE AGAINST MEMORY
  385.     JZ    STSC1    ;AH, HA, A FIND!
  386.     INX    H    ;UPDATE INDEX
  387.     DCX    B    ;UPDATE BYTE COUNTER
  388.     INR    B    ;CHECK FOR BEING DONE
  389.     DCR    B    
  390.     JNZ    SRC82    ;NOT DONE YET
  391.     INR    C    ;CHECK AGAIN
  392.     DCR    C
  393.     JNZ    SRC82    ;NOT DONE YET
  394.     INR    C    ;CLEAR THE ZERO FLAG FOR NO FIND
  395.     JMP    STSC1    ;OH WELL, YOU CAN'T WIN 'EM ALL!
  396. * RTN A.13
  397. * 8 BIT ADD TO HL
  398. * HL=HL+A
  399. * ONLY HL DISTURBED
  400. ADHL    PUSH    PSW    ;SAVE A
  401.     ADD    L    ;ADD LSB
  402.     MOV    L,A    ;STUFF IT BACK
  403.     JNC    ADHL1    ;NO CARRY, SO DON'T INCREMENT
  404.     INR    H    ;CORRECT FOR CARRY FROM LSB
  405. ADHL1    POP    PSW    ;RESTORE A
  406.     RET        ;DONE
  407. * RTN. A.14
  408. * 2 BYTE TABLE LOOK UP
  409. * BC = ITEM DE ON TABLE STARTING AT HL
  410. * A,D,E,H,L NOT DISTURBED
  411. TABLE    PUSH    PSW    ;SAVE REGISTERS
  412.     PUSH    D    
  413.     XCHG        ;SET UP FOR ADDRESS COMPUTATION
  414.     DAD    H    ;MULTIPLY ITEM # BY TWO
  415.     DAD    D    ;ADD IN BASE ADDRESS
  416.     DCX    H    ;GET ADDRESS OF MSB
  417.     MOV    B,M    ;STUFF IT INTO B
  418.     DCX    H    ;GET ADDRESS OF LSB
  419.     MOV    C,M    ;STUFF IT INTO C
  420.     XCHG        ;RESTORE HL
  421.     POP    D    ;RESTORE OTHER REGISTERS
  422.     POP    PSW
  423.     RET        ;DONE
  424. * THIS ROUTINE CHECKS THE INTEGRITY OF BASIC BY COMPUTING
  425. * THE MODULO 256 SUM OF ALL INSTRUCTIONS
  426. CHCK    LXI    H,STMSG+8    ;LAST ADDRESS
  427.     LXI    D,START+3    ;FIRST ADDRESS
  428.     PUSH    D    ;SAVE IT
  429.     CALL    SUB16    ;COMPUTE NUMBER OF BYTES
  430.     XCHG        ;TO DE
  431.     POP    H    ;GET FIRST ADDRESS BACK
  432.     XRA    A    ;CLEAR PARTIAL CHECKSUM
  433. CHCK1    ADD    M    ;ADD A BYTE
  434.     DCX    D    ;CHECK FOR DONENESS
  435.     INX    H    ;UPDATE INDEX
  436.     MOV    B,A    ;SAVE PARTIAL CHECKSUM
  437.     MOV    A,D    ;CHECK COUNT
  438.     ORA    E
  439.     MOV    A,B    ;PARTIAL CHECKSUM BACK
  440.     JNZ    CHCK1    ;NOT DONE YET
  441.     RET        ;DONE
  442. * MATH MODULE
  443. * RTN. B.1
  444. * TWO DIGIT BCD SUBTRACT
  445. * A,CARRY = B-C-CARRY 
  446. * B,C,D,E,H,L UNDISTURBED
  447. SUB2    PUSH    B    ;SAVE REGISTERS
  448.     MVI    A,0    ;CLEAR A WITHOUT TOUCHING CARRY
  449.     ADC    C    ;GET C+CARRY
  450.     DAA        ;BCD ADJUST
  451.     CMA        ;GET 1'S COMPLEMENT
  452.     SUI    66H    ;GET 9'S BCD COMPLEMENT
  453.     STC        ;GET READY TO CORRECT TO 10'S COMPLEMENT
  454.     ADC    B    ;ADD B AND CORRECTION TO 10'S COMPLEMENT
  455.     DAA        ;BCD ADJUST
  456.     POP    B    ;RESTORE REGISTERS
  457.     CMC        ;CORRECT CARRY
  458.     RET        ;FINI
  459. * RTN. B.2
  460. * ZERO REGISTER
  461. * ZEROES A BYTES STARTING AT HL
  462. ZERO    MVI    M,0    ;STORE A ZERO
  463.     INX    H    ;UPDATE INDEX
  464.     DCR    A    ;UPDATE COUNTER
  465.     JNZ    ZERO    ;LOOP FOR MORE BYTES
  466.     RET        ;DONE
  467. * RTN. B.3
  468. * SHIFT LEFT ONE BCD DIGIT (PACKED)
  469. * HL = ADDRESS OF MSB
  470. SFTL    PUSH    PSW    ;SAVE THE WORLD
  471.     PUSH    B
  472.     PUSH    D
  473.     PUSH    H
  474.     DCX    H    ;SET UP FOR FIRST SHIFT
  475.     MVI    E,5    ;SET UP SHIFT COUNT
  476. SFTL1    MOV    A,M    ;GET A BYTE
  477.     INX    H    ;GET THE NEXT BYTE TOO
  478.     MOV    D,M    
  479.     DCX    H    ;SET THE INDEX BACK
  480.     MVI    C,4    ;SET THE SHIFT COUNTER
  481. SFTL2    MOV    B,A    ;SHIFT LOOP, SAVE UPPER BYTE
  482.     MOV    A,D    ;SHIFT D LEFT ONE INTO CARRY
  483.     RAL
  484.     MOV    D,A
  485.     MOV    A,B    ;GET UPPER BYTE BACK
  486.     RAL        ;SHIFT THAT CARRY BACK IN
  487.     DCR    C    ;CHECK SHIFT COUNT
  488.     JNZ    SFTL2    ;LOOP FOR MORE SHIFTS
  489.     MOV    M,A    ;STORE THE SHIFTED DIGIT PAIR
  490.     DCR    E    ;CHECK BYTE COUNTER
  491.     INX    H    ;UPDATE INDEX
  492.     JNZ    SFTL1    ;LOOP FOR MORE BYTES
  493.     POP    H    ;PUT THE WORLD BACK, PLEASE.
  494.     POP    D
  495.     POP    B
  496.     POP    PSW
  497.     DCX    H    ;CORRECT INDEX
  498.     RET        ;ALL DONE!
  499. * RTN. B.4
  500. * SHIFT BUFFER DOWN
  501. * SHIFTS BY MOVING INDEX TO SAVE TIME
  502. * IN: A = PLACES TO SHIFT
  503. *    HL = ADDRESS OF MSB
  504. *     B = 00 OR 99 FOR POSITIVE OR NEGATIVE
  505. * OUT: HL = ADDRESS OF MSB
  506. SHFT    RRC        ;CHECK LSB FOR ODDNESS
  507.     CC    SHFT1    ;IF IT'S ODD, SHIFT LEFT ONE DIGIT
  508.     ANI    7FH    ;STRIP UPPER BIT OFF
  509. SHFT5    ANA    A    ;SET FLAGS
  510.     RZ        ;RETURN IF ALL DONE
  511.     DCX    H    ;GO BACK ONE
  512.     MOV    M,B    ;SET IN FILLER
  513.     DCR    A    ;DECREMENT COUNTER
  514.     JMP    SHFT5    ;LOOP TO SEE IF DONE YET
  515. SHFT1    CALL    SFTL    ;SHIFT LEFT
  516.     PUSH    PSW    ;SAVE A
  517.     MOV    A,B    ;GET FILLER BYTE
  518.     ANI    0F0H    ;STRIP OFF UPPER DIGIT
  519.     MOV    C,A    ;STICK IT IN C
  520.     MOV    A,M    ;GET DIGIT FROM MEMORY
  521.     ANI    0FH    ;STRIP OFF LOWER DIGIT
  522.     ORA    C    ;SET IN THE UPPER DIGIT
  523.     MOV    M,A    ;STICK IT BACK TO MEMORY
  524.     POP    PSW    ;RESTORE A
  525.     RET        ;DONE
  526. * RTN. B.5
  527. * ADD EXPONENTS
  528. * B,D = SIGN BYTES, C,E = EXPONENTS
  529. * OUT: B,C = SIGN BYTE, EXPONENT RESULT
  530. * IF AN UNDER/OVERFLOW OCCURS, THE
  531. * MATH ERROR FLAG IS SET.
  532. * CARRY FLAG IS SET ON EXIT IF AN ERROR OCCURRED
  533. EXAD    MOV    A,B    ;GET STATE OF BC
  534.     XRA    D    ;GET A 0 IF SIGNS ARE THE SAME
  535.     ANI    40H    ;LOOK AT SIGN BIT ONLY
  536.     JNZ    EXAD1    ;JUMP IF DIFFERENT SIGNS
  537.     MOV    A,C    ;ADD THE EXPONENTS
  538.     ADD    E
  539.     DAA        ;BCD ADJUST
  540.     MOV    C,A    ;PUT ANSWER IN C
  541.     RNC        ;RETURN IF NO ERROR
  542.     MOV    A,B    ;FIGURE OUT IF UNDER OR OVER FLOW
  543.     RLC        ;GET SIGN BIT TO LSB
  544.     RLC
  545.     ANI    1    ;CLEAR ALL OTHERS
  546.     INR    A    ;SET UNDER/OVERFLOW BIT
  547.     STA    MERR    ;STORE IT TO MATH ERROR FLAG
  548.     STC        ;SET ERROR FLAG
  549.     RET        ;DONE
  550. EXAD1    ANA    B    ;CHECK IF BC IS NEGATIVE
  551.     JNZ    EXAD3    ;YUP, SO SKIP THE SWAP
  552.     PUSH    B    ;SWAP BC AND DE
  553.     PUSH    D
  554.     POP    B
  555.     POP    D
  556. EXAD3    PUSH    B    ;SAVE BC
  557.     MOV    B,E    ;SET UP FOR SUBTRACT
  558.     CALL    SUB2    ;SUBTRACT IN BCD
  559.     POP    B    ;GET BC BACK
  560.     MVI    B,0    ;SET SIGN POSITIVE
  561.     MOV    C,A    ;SET ANSWER IN C
  562.     RNC        ;RETURN IF STILL POSITIVE AFTER SUBTRACT
  563.     CMA        ;GET 9'S COMPLEMENT
  564.     SUI    66H    ;GET 10'S COMPLEMENT
  565.     ADI    1    ;CORRECT FOR 10'S COMPLEMENT
  566.     DAA        ;BCD ADJUST
  567.     MOV    C,A    ;SET NEW ANSWER IN C
  568.     MVI    B,040H    ;SET SIGN NEGATIVE
  569.     RET        ;ALL DONE
  570. * RTN. B.6
  571. * NORMALIZE WORKING REGISTER
  572. * IN: HL = ADDRESS OF REFERENCE NUMBER
  573. *    DE = ADDRESS OF WORKING REGISTER
  574. * OUT: HL = ADDRESS OF REFERENCE NUMBER
  575. *      DE = ADDRESS OF MANTISSA, NORMALIZED
  576. *      BC = NORMALIZED EXPONENT
  577. NORM    MVI    B,0    ;CLEAR 0'S COUNTER
  578. NORM1    LDAX    D    ;GET A BYTE
  579.     ANI    0F0H    ;LOOK AT UPPER BCD DIGIT
  580.     JNZ    NORM3    ;JUMP IF DIGIT IS NONZERO
  581.     MOV    A,B    ;UPDATE 0'S COUNTER
  582.     ADI    1    
  583.     DAA        ;BCD ADJUST
  584.     MOV    B,A    ;PUT IT BACK
  585.     LDAX    D    ;NOW LET'S TRY THE LOWER DIGIT
  586.     ANI    0FH    ;STRIP OFF LOWER BCD DIGIT
  587.     JNZ    NORM3    ;JUMP IF DIGIT IS NONZERO
  588.     MOV    A,B    ;UPDATE 0'S COUNTER
  589.     ADI    1
  590.     DAA        ;BCD ADJUST
  591.     MOV    B,A    ;STUFF IT BACK
  592.     INX    D    ;GET NEXT BYTE ADDRESS
  593.     MVI    A,16H    ;CHECK FOR A ZERO RESULT
  594.     CMP    B
  595.     JNZ    NORM1    ;LOOP TO CHECK SOME MORE
  596.     DCX    D    ;LOOKS LIKE ALL ZEROES
  597.     DCX    D    ;CORRECT THE INDEX
  598.     DCX    D    ;TO GIVE A ZEROES MANTISSA
  599.     DCX    D
  600.     LXI    B,0    ;SET UP A ZERO EXPONENT
  601.     RET
  602. NORM3    MVI    A,1    ;SEE IF B IS ODD
  603.     ANA    B
  604.     JZ    NORM4    ;NOPE, SO DON'T SHIFT
  605.     XCHG        ;SWAP
  606.     INX    H    ;CORRECT THE INDEX
  607.     CALL    SFTL    ;SHIFT THE MANTISSA LEFT ONE
  608.     XCHG        ;PUT EVERYTHING BACK WHERE IT BELONGS
  609. NORM4    MOV    C,B    ;SET UP FOR OFFSET SUBTRACTION
  610.     MVI    B,40H    ;SET SIGN BIT
  611.     PUSH    D    ;SAVE DE
  612.     LXI    D,8    ;SET UP DE
  613.     CALL    EXAD    ;PERFORM SUBTRACTION
  614.     MOV    D,M    ;GET REFERENCE PARAMETERS
  615.     INX    H
  616.     MOV    E,M
  617.     DCX    H
  618.     CALL    EXAD    ;COMPUTE NORMALIZED EXPONENT
  619.     POP    D    ;RESTORE DE
  620.     RET        ;DONE
  621. * RTN. B.7
  622. * FIXED POINT ADD
  623. * NUMBERS POINTED TO BY DE,HL ARE ADDED TO BC
  624. * THE NUMBER AT HL PROVIDES THE ROUNDING BYTE
  625. * A = NUMBER OF BYTES TO ADD
  626. * ON RETURN, A=40H IF A SIGN CHANGE HAS OCCURED
  627. FXAD    PUSH    B    ;SAVE DESTINATION
  628.     STA    QFLAG    ;SAVE FLOATING/FIXED INDICATION
  629.     MOV    C,A    ;SAVE NUMBER OF BYTES
  630.     MVI    B,0    ;CLEAR B
  631.     XTHL        ;GET DESTINATION TO HL
  632.     DAD    B    ;ADD OFFSET
  633.     XTHL        ;PUT IT BACK ON THE STACK
  634.     DAD    B    ;ADD OFFSET
  635.     XCHG        ;GET DE TO HL
  636.     DAD    B    ;ADD OFFSET
  637.     PUSH    B    ;SAVE COUNT
  638.     XCHG        ;SWAP 'EM
  639.     PUSH    D    ;SAVE ONE SOURCE
  640.     LXI    D,WORK2+8    ;GET DESTINATION
  641.     LXI    B,4    ;NUMBER OF BYTES
  642.     CALL    MVDN    ;MOVE LESS SIGNIFICANT BITS IN
  643.     POP    D    ;RESTORE
  644.     POP    B
  645.     XCHG        ;SWAP 'EM BACK
  646.     XRA    A    ;CLEAR CARRY
  647. FXAD1    DCX    D    ;UPDATE INDEXES
  648.     DCX    H    
  649.     LDAX    D    ;GET A BYTE TO ADD
  650.     ADC    M    ;ADD MEMORY AND THE CARRY
  651.     DAA        ;BCD ADJUST
  652.     XTHL        ;GET DESTINATION
  653.     DCX    H    ;UPDATE INDEX
  654.     MOV    M,A    ;STORE THE RESULT
  655.     XTHL        ;STUFF IT BACK ON THE STACK
  656.     DCR    C    ;CHECK BYTES COUNTER
  657.     JNZ    FXAD1    ;LOOP FOR MORE BYTES TO ADD
  658.     RAL        ;GET CARRY TO A
  659.     ANI    1    ;STRIP ALL BUT LOWER BIT
  660.     POP    H    ;CLEAN UP STACK
  661.     MOV    C,A    ;SAVE A TO C
  662.     LDA    QFLAG    ;GET FLOATING/FIXED INDICATION
  663.     CPI    4    ;CHECK FOR FLOATING
  664.     JNZ    FXAD3    ;SKIP ROUNDING IF FIXED
  665.     PUSH    H    ;SAVE ADDRESS
  666.     LXI    H,WORK2    ;INITIALIZE FIRST DIGIT SEARCH
  667.     MVI    B,8D    ;MAX BYTE COUNT
  668. FXAD4    MVI    A,0F0H    ;MASK UPPER DIGIT
  669.     ANA    M    ;AND WITH MEMORY
  670.     JNZ    FXAD5    ;LEAP IF NONZERO
  671.     MVI    A,0FH    ;MASK LOWER DIGIT
  672.     ANA    M    ;AND WITH MEMORY
  673.     JNZ    FXAD6    ;LEAP IF NONZERO
  674.     INX    H    ;UPDATE INDEX
  675.     DCR    B    ;CHECK COUNTER
  676.     JNZ    FXAD4    ;LOOP FOR MORE CHECKING
  677. FXAD9    POP    H    ;RESTORE ADDRESS
  678.     JMP    FXAD3    ;NO ROUNDING IS REQUIRED FOR ZEROES!!
  679. FXAD5    MVI    A,50H    ;GET ROUNDING NUMBER FOR UPPER FIND
  680.     JMP    FXAD7    ;SKIP
  681. FXAD6    MVI    A,5H    ;GET ROUNDING NUMBER FOR LOWER FIND
  682. FXAD7    LXI    D,8D    ;GET OFFSET
  683.     DAD    D    ;ADD TO FIND ADDRESS
  684.     ADD    M    ;ADD THE ROUNDING NUMBER
  685.     DAA        ;BCD ADJUST
  686. FXAD8    JNC    FXADA    ;JUMP WHEN DONE
  687.     DCX    H    ;UPDATE INDEX
  688.     MOV    A,M    ;GET A BYTE
  689.     ADI    1    ;INCREMENT
  690.     DAA        ;BCD ADJUST
  691.     MOV    M,A    ;STORE IT BACK
  692.     JC    FXAD8+3    ;LOOP FOR MORE ADDS
  693. FXADA    POP    H    ;GET ADDRESS BACK TO HL
  694.     DCX    H    ;GET OVERFLOW ADDRESS
  695.     MOV    A,M    ;GET IT TO A
  696.     MVI    M,0    ;CLEAR IT OUT
  697.     INX    H    ;RESTORE ADDRESS
  698.     ORA    C    ;SET IN OLD OVERFLOW
  699.     MOV    C,A    ;BACK TO C
  700. FXAD3    LDA    ASFLG    ;GET ADD/SUBTRACT FLAG
  701.     ANA    A    ;SET FLAGS
  702.     JNZ    FXAD2    ;JUMP IF SUBTRACT WAS JUST PERFORMED
  703.     DCX    H    ;GET OVERFLOW ADDRESS
  704.     MOV    M,C    ;STORE ANY OVERFLOW FOR ADD OPERATION
  705.     XRA    A    ;CLEAR A FOR NO SIGN CHANGE
  706.     RET        ;DONE
  707. FXAD2    XRA    A    ;CLEAR A
  708.     DCR    C    ;CHECK FOR OVERFLOW
  709.     RZ        ;OK, NORMAL FOR SUBTRACT
  710.     MVI    C,5    ;OH,OH, SIGN CHANGE, SO COMPLEMENT
  711.     CALL    CMPL    ;GET 10'S COMPLEMENT
  712.     MVI    A,080H    ;SET SIGN CHANGE FLAG
  713.     RET        ;DONE
  714. * RTN. B.8
  715. * 10'S COMPLEMENT BUFFER BCD
  716. * COMPLEMENTS C BYTES STARTING AT HL
  717. CMPL    PUSH    B    ;SAVE BYTES COUNTER FOR LATER
  718. CMPL1    MOV    A,M    ;GET A BYTE
  719.     CMA        ;GET 1'S COMPLEMENT
  720.     SUI    66H    ;GET 9'S COMPLEMENT
  721.     MOV    M,A    ;STICK IT BACK
  722.     INX    H    ;UPDATE INDEX
  723.     DCR    C    ;CHECK BYTES COUNTER
  724.     JNZ    CMPL1    ;LOOP FOR MORE BYTES
  725.     STC        ;SET UP FOR 10'S COMPLEMENT
  726.     POP    B    ;RESTORE BYTE COUNT
  727. CMPL2    DCX    H    ;UPDATE INDEX
  728.     MOV    A,M    ;GET BYTE BACK
  729.     ACI    0    ;ADD CARRY FOR 10'S COMPLEMENT
  730.     DAA        ;BCD ADJUST
  731.     MOV    M,A    ;STICK IT BACK
  732.     RNC        ;RETURN IF NO CARRY PROPAGATE
  733.     DCR    C    ;CHECK BYTES COUNTER
  734.     JNZ    CMPL2    ;LOOP FOR MORE BYTES
  735.     RET        ;DONE
  736. * RTN. B.9
  737. * FLOATING POINT ADD AND SUBTRACT
  738. * ADD ENTERS AT FPADD
  739. * SUBTRACT ENTERS AT FPSUB
  740. * PERFORMS (HL)+-(DE), PUTS RESULT IN (BC)
  741. FPSUB    PUSH    B    ;SAVE REGISTERS
  742.     PUSH    H
  743.     XCHG        ;GET 'FROM' TO HL
  744.     INX    H    ;GET ADDRESS OF MSD
  745.     INX    H
  746.     MOV    A,M    ;GET THE MSD BYTE
  747.     DCX    H    ;RESTORE THE ADDRESS
  748.     DCX    H
  749.     LXI    D,TEMP1    ;GET ADDRESS OF TEMPORARY 1
  750.     LXI    B,6    ;GET NUMBER OF BYTES
  751.     CALL    MVDN    ;MOVE TO TEMPORARY
  752.     ANA    A    ;SET FLAGS
  753.     JZ    FPSB1    ;SKIP SIGN CHANGE IF ZERO
  754.     LDAX    D    ;GET SIGN BYTE
  755.     XRI    80H    ;CHANGE SIGN OF MANTISSA
  756.     STAX    D    ;PUT IT BACK
  757. FPSB1    POP    H    ;RESTORE REGISTERS
  758.     POP    B
  759. FPADD    XRA    A    ;CLEAR ADD/SUBTRACT FLAG
  760.     STA    ASFLG
  761.     PUSH    H    ;SAVE HL
  762.     LXI    H,WORK1    ;CLEAR OUT WORKING REGISTERS 1 AND 2
  763.     MVI    A,24    ;NUMBER OF BYTES
  764.     CALL    ZERO    ;CLEAR THEM
  765.     POP    H    ;RESTORE HL
  766.     PUSH    B    ;SAVE DESTINATION
  767.     LDAX    D    ;GET SIGNS BYTE
  768.     XRA    M    ;GET BITS DIFFERENT THAN OTHER NUMBER
  769.     ANI    80H    ;GET MANTISSA SIGN BIT ALONE
  770.     JZ    FPAS1    ;JUMP IF SIGNS ARE THE SAME
  771.     ANA    M    ;CHECK SIGN OF NUMBER AT HL
  772.     JNZ    FPAS2    ;HL NEGATIVE ALREADY, SO SKIP SWAP
  773.     XCHG        ;PUT NEGATIVE NUMBER IN HL
  774. FPAS2    PUSH    D    ;SAVE OTHER NUMBER
  775.     LXI    B,6    ;GET NUMBER OF BYTES
  776.     LXI    D,TEMP2    ;GET ADDRESS TO MOVE TO
  777.     CALL    MVDN    ;MOVE IT
  778.     PUSH    D    ;SAVE NUMBER LOCATION
  779.     XCHG        ;PUT DESTINATION IN HL
  780.     INX    H    ;MOVE UP TO MANTISSA
  781.     INX    H
  782.     MVI    C,4    ;NUMBER OF BYTES
  783.     CALL    CMPL    ;DO A 10'S COMPLEMENT
  784.     POP    H    ;RESTORE LOCATION
  785.     POP    D    ;RESTORE THE OTHER LOCATION
  786.     MVI    A,0FFH    ;SET ADD/SUBTRACT FLAG
  787.     STA    ASFLG
  788. FPAS1    PUSH    H    ;SAVE LOCATIONS
  789.     PUSH    D
  790.     MOV    B,M    ;GET EXPONENTS AND SIGNS
  791.     INX    H
  792.     MOV    C,M
  793.     XCHG
  794.     MOV    D,M
  795.     INX    H
  796.     MOV    E,M
  797.     PUSH    B    ;SAVE ORIGINAL EXPONENT
  798.     MVI    A,40H    ;COMPLEMENT SIGN BIT OF ONE
  799.     XRA    B    ;FOR SUBTRACT
  800.     MOV    B,A    ;STICK THE COMPLEMENTED BIT BACK
  801.     PUSH    D    ;SAVE ORIGINAL EXPONENT
  802.     CALL    EXAD    ;COMPUTE DIFFERENCE IN EXPONENTS
  803.     POP    D    ;RESTORE ORIGINAL EXPONENT
  804.     MOV    A,D    ;SAVE ORIGINAL EXPONENT
  805.     POP    D    ;GET THE OTHER ORIGINAL BACK
  806.     MOV    E,A    ;TWO ORIGINALS IN D,E
  807.     PUSH    PSW    ;SAVE ANY CARRY FLAG FOR LATER
  808.     MOV    A,E    ;COMPUTE A'B'R'+AB'+ABR TO FIND LARGER
  809.     ORA    D
  810.     CMA
  811.     ANA    B
  812.     MOV    H,A
  813.     MOV    A,B
  814.     ANA    E
  815.     ANA    D
  816.     ORA    H
  817.     MOV    H,A
  818.     MOV    A,D
  819.     CMA
  820.     ANA    E
  821.     ORA    H
  822.     ANI    40H    ;SEPARATE SIGN BIT
  823.     POP    H    ;GET LOCATIONS BACK
  824.     POP    D
  825.     XTHL
  826.     JNZ    FPAS4    ;JUMP IF NO SWAP NECCESARY
  827.     XCHG        ;SWAP LOCATIONS TO GET LARGER TO HL
  828. FPAS4    POP    PSW    ;GET THE CARRY FLAG BACK
  829.     JC    FPAS7    ;JUMP IF NO NEED TO ADD
  830.     MOV    A,C    ;GET EXPONENTS DIFFERENCE TO A
  831.     CPI    9    ;SEE IF > 8
  832.     JP    FPAS7    ;YES, SO NO ADD REQUIRED
  833.     PUSH    H    ;SAVE LOCATION
  834.     PUSH    D    ;SAVE LOCATION
  835.     PUSH    B    ;SAVE THE DIFFERENCE
  836.     XCHG        ;SET UP TO MOVE MANTISSA
  837.     LXI    D,WORK1+4    ;GET WORKING REGISTER ADDRESS
  838.     INX    H    ;GET MANTISSA ADDRESS
  839.     INX    H
  840.     LXI    B,4    ;GET NUMBER OF BYTES
  841.     CALL    MVDN    ;MOVE IT IN
  842.     POP    B    ;GET THE DIFFERENCE BACK
  843.     XCHG        ;GET MANTISSA LOCATION TO HL
  844.     POP    D    ;GET THE NUMBER LOCATION
  845.     LDAX    D    ;GET THE SIGNS BYTE
  846.     ANI    80H    ;CHECK SIGN
  847.     JZ    FPAS5    ;POSITIVE, SO LEAVE ZEROES
  848.     LDA    ASFLG    ;CHECK FOR SUBTRACT OPERATION
  849.     ANA    A    ;SET FLAGS
  850.     JZ    FPAS5    ;JUMP IF BOTH SIGNS THE SAME
  851.     MVI    A,99H    ;GET A 99
  852. FPAS5    MOV    B,A    ;STICK IT IN B
  853.     MOV    A,C    ;GET NUMBER OF SHIFTS
  854.     CALL    SHFT    ;SHIFT THE BUFFER
  855.     XCHG        ;PUT ADDRESS TO DE
  856.     POP    H    ;GET THE LOCATION
  857.     PUSH    H    ;SAVE IT AGAIN
  858.     INX    H    ;GET MANTISSA LOCATION
  859.     INX    H
  860.     LXI    B,WORK2+4D     ;GET RESULT ADDRESS
  861.     MVI    A,4    ;GET NUMBER OF BYTES
  862.     XCHG        ;GET REGISTERS IN THE RIGHT PLACE
  863.     CALL    FXAD    ;ADD THE MANTISSAS
  864.     POP    H    ;GET ADDRESS OF REFERENCE NUMBER
  865.     PUSH    H    ;SAVE REFERENCE LOCATION
  866.     PUSH    PSW    ;SAVE ANY SIGN CHANGE
  867.     LDA    TEMP2    ;CHANGE SIGN OF TEMP2
  868.     XRI    80H
  869.     STA    TEMP2
  870.     XRA    A    ;CLEAR ERROR FLAG
  871.     STA    MERR
  872.     LXI    D,WORK2    ;GET ADDRESS OF WORKING REGISTER
  873.     CALL    NORM    ;NORMALIZE RESULT
  874.     POP    PSW    ;GET ADDRESS FOR RESULT
  875.     POP    H    ;GET ANY SIGN CHANGE
  876.     XRA    M    ;CHANGE SIGN IF NEEDED
  877.     POP    H    ;CLEAN UP THE STACK
  878.     PUSH    PSW    ;SAVE SIGNS BYTE
  879.     MOV    A,B    ;GET THE EXPONENT SIGN
  880.     ANI    40H    ;STRIP OFF THE SIGN BIT
  881.     MOV    B,A    ;BACK TO B
  882.     POP    PSW    ;GET SIGNS BYTE BACK
  883.     ANI    0BFH    ;CLEAR THE SIGN BIT
  884.     ORA    B    ;SET THE REAL SIGN BIT IN
  885.     MOV    M,A    ;STORE SIGNS BYTE
  886.     INX    H    ;UPDATE INDEX
  887.     MOV    M,C    ;STORE EXPONENT
  888.     XCHG        ;SWAP ADDRESSES FOR MANTISSA MOVE
  889.     INX    D    ;GET RIGHT ADDRESS
  890.     LXI    B,4    ;NUMBER OF BYTES
  891.     CALL    MVDN    ;MOVE IT
  892.     RET
  893. FPAS6    MOV    A,D    ;GET SIGNS BYTE
  894.     POP    D    ;GET LOCATIONS BACK
  895.     POP    H
  896.     ANI    40H    ;CHECK EXPONENT SIGN
  897.     JNZ    FPAS7    ;DE ALREADY LITTLE ONE
  898.     XCHG        ;MAKE DE THE LITTLE ONE
  899. FPAS7    POP    D    ;GET DESTINATION
  900.     LXI    B,6    ;GET NUMBER OF BYTES
  901.     CALL    MVDN    ;MOVE IT
  902.     RET
  903. MTBLE    DB    0,1,2,3,4,5,6,7,8,9
  904.     DS    6
  905.     DB    0,2,4,6,8,10H,12H,14H,16H,18H
  906.     DS    6
  907.     DB    0,3,6,9,12H,15H,18H,21H,24H,27H
  908.     DS    6
  909.     DB    0,4,8,12H,16H,20H,24H,28H,32H,36H
  910.     DS    6
  911.     DB    0,5,10H,15H,20H,25H,30H,35H,40H,45H
  912.     DS    6
  913.     DB    0,6,12H,18H,24H,30H,36H,42H,48H,54H
  914.     DS    6
  915.     DB    0,7,14H,21H,28H,35H,42H,49H,56H,63H
  916.     DS    6
  917.     DB    0,8,16H,24H,32H,40H,48H,56H,64H,72H
  918.     DS    6
  919.     DB    0,9,18H,27H,36H,45H,54H,63H,72H,81H
  920. * RTN. B.10
  921. * MULTIPLY TWO BCD DIGITS BY TWO DIGITS, FOUR DIGIT
  922. * PRODUCT. B * C = BC
  923. MUL2    INR    B    ;CHECK FOR B = 0
  924.     DCR    B
  925.     JZ    MUL20    ;YUP, SO CLEAR BC AND RETURN
  926.     INR    C    ;CHECK FOR C = 0
  927.     DCR    C    
  928.     JZ    MUL20    ;YUP, SO CLEAR BC AND RETURN
  929.     PUSH    D    ;SAVE DE,HL
  930.     PUSH    H
  931.     LXI    D,0    ;CLEAR PRODUCT REGISTERS
  932.     MOV    A,C    ;GET A DIGIT
  933.     ANI    0FH
  934.     JZ    MUL21    ;NO MULTIPLY NEEDED
  935.     MOV    L,A    ;SAVE IT
  936.     MOV    A,B    ;GET ANOTHER DIGIT
  937.     ANI    0F0H
  938.     JZ    MUL21    ;NO MULTIPLY NEEDED
  939.     ADD    L    ;GENERATE TABLE ADDRESS
  940.     LXI    H,MTBLE-10H
  941.     ADD    L
  942.     JNC    MUL25
  943.     INR    H
  944. MUL25    MOV    L,A
  945.     MOV    E,M    ;GET PRODUCT TO E
  946. MUL21    MOV    A,B    ;GET A DIGIT
  947.     ANI    0FH
  948.     JZ    MUL22    ;NO MULTIPLY NEEDED
  949.     MOV    L,A
  950.     MOV    A,C    ;GET ANOTHER ONE
  951.     ANI    0F0H
  952.     JZ    MUL22    ;NO MULTIPLY NEEDED
  953.     ADD    L    ;GENERATE TABLE ADDRESS
  954.     LXI    H,MTBLE-10H
  955.     ADD    L
  956.     JNC    MUL28
  957.     INR    H
  958. MUL28    MOV    L,A
  959.     MOV    A,M    ;GET PRODUCT TO A
  960.     ADD    E    ;ADD TO PRODUCT REGISTER
  961.     DAA        ;BCD ADJUST
  962.     MOV    E,A    ;STUFF IT IN
  963.     JNC    MUL22    ;NO CARRY PROPAGATE
  964.     INR    D    ;CARRY
  965. MUL22    XCHG        ;SET UP TO SHIFT PRODUCT REGISTER ONE DIGIT
  966.     DAD    H    ;SHIFT LEFT FOUR PLACES
  967.     DAD    H
  968.     DAD    H
  969.     DAD    H
  970.     XCHG        ;PUT IT BACK
  971.     MOV    A,C    ;GET A DIGIT
  972.     ANI    0FH
  973.     JZ    MUL23    ;NO MULTIPLY NEEDED
  974.     MOV    L,A
  975.     MOV    A,B    ;GET ANOTHER DIGIT
  976.     ANI    0FH
  977.     JZ    MUL23    ;NO MULTIPLY NEEDED
  978.     RLC        ;SHIFT LEFT 4
  979.     RLC    
  980.     RLC
  981.     RLC
  982.     ADD    L    ;GENERATE TABLE ADDRESS
  983.     LXI    H,MTBLE-10H
  984.     ADD    L
  985.     JNC    MUL26
  986.     INR    H
  987. MUL26    MOV    L,A
  988.     MOV    A,M    ;GET PARTIAL PRODUCT
  989.     ADD    E    ;ADD IT TO PRODUCT REGISTER
  990.     DAA
  991.     MOV    E,A    ;PUT RESULT IN
  992.     JNC    MUL23    ;NO CARRY
  993.     INR    D    ;PROPAGATE CARRY
  994. MUL23    MOV    A,B    ;GET A DIGIT
  995.     ANI    0F0H
  996.     JZ    MUL24    ;NO MULTIPLY NEEDED
  997.     MOV    L,A    ;SAVE IT
  998.     MOV    A,C    ;GET ANOTHER DIGIT
  999.     ANI    0F0H
  1000.     JZ    MUL24    ;NO MULTIPLY NEEDED
  1001.     RLC!RLC!RLC!RLC    ;LEFT SHIFT 4
  1002.     ADD    L    ;GENERATE TABLE ADDRESS
  1003.     LXI    H,MTBLE-10H
  1004.     ADD    L
  1005.     JNC    MUL27
  1006.     INR    H
  1007. MUL27    MOV    L,A
  1008.     XRA    A    ;CLEAR CARRY
  1009.     MOV    A,D    ;GET PRODUCT REGISTER
  1010.     DAA        ;ADJUST FOR ANY PREVIOUS CARRYS
  1011.     ADD    M    ;ADD NEW PRODUCT
  1012.     DAA        ;BCD ADJUST
  1013.     MOV    D,A    ;STUFF IT BACK
  1014. MUL24    XRA    A    ;CLEAR CARRYS
  1015.     MOV    A,D    ;ADJUST D IN CASE OF PREVIOUS CARRYS
  1016.     DAA
  1017.     MOV    B,A    ;PUT IT IN B
  1018.     MOV    C,E    ;MOVE E TO C
  1019.     POP    H    ;RESTORE REGISTERS
  1020.     POP    D
  1021.     RET        ;DONE!!!
  1022. MUL20    LXI    B,0    ;CLEAR BC
  1023.     RET        ;FAST EXIT
  1024. LINK1    LINK    A:TBASICA2
  1025.