home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol070 / xref141.asm < prev   
Assembly Source File  |  1984-04-29  |  43KB  |  1,634 lines

  1.     TITLE    'XREF.ASM  Ver 1.41    03/15/82'
  2.     PAGE    0
  3.  
  4. ;********************************************************
  5. ;                            *
  6. ; This program generates a cross reference list for all    *
  7. ; Symbols in a CPM assembler program.  Its input is    *
  8. ; either an assembler source file (FN.ASM) or an assem-    *
  9. ; bler listing file (FN.PRN).  It will number the lines    *
  10. ; and generate a cross reference listing at the end of    *
  11. ; the program.  The output defaults to the CPM list    *
  12. ; device, but it can be directed to the console or to a *
  13. ; disk file instead.  If the output is directed to a    *
  14. ; disk file, that file will be named FN.XRF.  The    *
  15. ; filename will be the filename of the input file.    *
  16. ; It is invoked by entering:                *
  17. ;        XREF FN.ASM    (OUTPUT TO LIST DEVICE)    *
  18. ;        XREF FN.PRN CON    (OUTPUT TO CONSOLE)    *
  19. ;        XREF FN.ASM D    (OUTPUT TO DISK-DEFAULT    *
  20. ;                        DRIVE)    *
  21. ;        XREF FN.PRN B:D    (OUTPUT TO DISK-DRIVE    *
  22. ;                NUMBER SPECIFIED)    *
  23. ;                            *
  24. ; To invoke help function enter:            *
  25. ;        XREF ?                    *
  26. ;                            *
  27. ;********************************************************
  28.  
  29. ;03/15/82 This program would lock up if there was a
  30. ;comment line that started with an asterisk('*') instead
  31. ;of a semicolon.  The program then processed the whole
  32. ;line as a valid line of assemble code.  This usually
  33. ;resulted in the cross reference program locking up if
  34. ;there were a lot lines that started with an asterisk.
  35. ;The program now treats an asterisk the same as a
  36. ;semicolon.  This was done by changing the table CTAB1
  37. ;so that the program branches to LSEMI when it finds an
  38. ;asterisk. Also fixed bug that occurred when the last
  39. ;record of a file was completely filled with data and
  40. ;thus had no control Z's(EOF characters) in it.  This
  41. ;was done by always placing two control Z's after the
  42. ;last record was read.  Finally fixed a bug that showed
  43. ;up only when a program had no symbols or labels in it.
  44. ;Added a check for an empty symbol table before attempting
  45. ;to print the symbol table.  (JRM)
  46.  
  47. ;03/06/82 Changed the code so that the size of output
  48. ;disk buffer can be specified at assembly time.  The
  49. ;size is set by OUTSECT which equals the number of disk
  50. ;sectors to be written when the buffer is full.
  51. ;Implemented the same feature for disk input.  INSECT sets
  52. ;the number of disk records to be read into the input
  53. ;buffer.  On file type PRN the was a bug.  Whenever the
  54. ;first symbol on a line was preceded by a character, the
  55. ;line was not listed in the cross reference listing.  This
  56. ;was caused by skipping over the first 16 characters in the
  57. ;line on a CR(carriage return) instead of on a LF(line feed).
  58. ;This bug has been fixed.  Added help function.  This is
  59. ;invoked by entering  XFER ?.  (JRM)
  60.  
  61.  
  62. ;03/03/82 Added a 2k buffer for disk output writes.  This
  63. ;was done to speed up the execution of program when disk
  64. ;output was specified.  Fixed bug when page size was
  65. ;specified.  CPM assembler was not doing the conditional
  66. ;IF assembly correctly.  Changed the code to test if page
  67. ;size is in effect by testing LPAGE to see if it is zero.
  68. ;Changed test to question to erase existing disk cross
  69. ;reference file to handle lower case as well as upper
  70. ;case.  (JRM)
  71.  
  72. ;02/20/82 Changed code so that the size of the symbol
  73. ;that is referenced in the cross reference listing can
  74. ;be set at assembly time.  The original program only
  75. ;allowed for 5 char per symbol.  This did not allow for
  76. ;separate unique symbols where the uniqueness occurred
  77. ;after the first 5 characters.  I tested this function
  78. ;for a length of 5, 8, and 10 characters labels.  It
  79. ; should work for any length of symbol.  I also
  80. ;allowed the '$' character to be a valid character in a
  81. ;symbol.  The equ SYMSIZ was added and all other values
  82. ;and variables that are dependent on the size of the
  83. ;symbol are expressed using SYMSIZ.
  84. ;        Example: SSIZ EQU SYMSIZ+3
  85. ;Added a disk file output option.  The output disk file
  86. ;will the filename of the input file and always a file
  87. ;type of 'XRF'.  This option is enabled by specifying
  88. ;a 'D' as the second parameter when executing the program.
  89. ;The user can optionally specify a different drive than
  90. ;the default drive for the cross reference disk output.
  91. ;        Example: XREF FN.ASM D
  92. ;             XREF FN.PRN B:D
  93. ;                        (JRM)
  94.  
  95. ;11/01/81 Changed the code so that the hex addresses and
  96. ;the hex translation of the instructions are not included
  97. ;in the cross reference listing for PRN files from CPM
  98. ;assembler.  The listing can now be directed at execution
  99. ;time to the console or the list (LST:) device.  If the
  100. ;listing is to be displayed on the console enter
  101. ;    XREF FN.FT C
  102. ;If the listing is to go to the list device enter
  103. ;    XREF FN.FT
  104. ;In other words, the output goes to the list device by
  105. ;default. (JRM)
  106.  
  107. ;Modifications 4/5/79, 4/26/79, 5/3/79, 8/28/79 by SAN:
  108. ;Suppress initial page eject, add page eject at completion
  109. ;Automatically convert lower case in source file to UPPER
  110. ;Abort execution if ^C typed, but ignore other typed chars
  111. ;Add ELSE, PAGE to reserved word table
  112.  
  113. ;********************************************************
  114.  
  115. ;Number of lines per output page set by LPAGE EQUate
  116.  
  117. ;Number of symbol refs per table entry set by NREFS EQUate
  118. ;    This value should be set to the average number of
  119. ;    references that a symbol will have in program.  It
  120. ;    is used to build the symbol reference table entries.
  121. ;    Each entry will be equal to (NREFS * 2)+2.  If it is
  122. ;    made unnecessarily large, then the symbol reference
  123. ;    table will be very large with a lot of unused slots.
  124. ;    Example: a program with 300 symbols will require a
  125. ;    reference table that is at least 12600 bytes if
  126. ;    NREFS=20, whereas the same program will require a
  127. ;    reference table that is at least 3600 bytes if
  128. ;    NREFS=5.  Each symbol that exceeds NREFS references
  129. ;    will require ((Total references/NREFS)rounded up)
  130. ;    reference table entries.  Recommended values: 3-5.
  131.  
  132. ;Number of symbol references to be printed per output line
  133. ;    This is set by LREFS EQUate.  It should be a multiple
  134. ;    of NREFS.  If it is not, then the first number that is
  135. ;    less than LREFS and is a multiple of NREFS will be
  136. ;    printed on the line.  Example: if NREFS is 5 and
  137. ;    LREFS is 13, then only 10 entries will be printed per
  138. ;    line.  The total number of references that will fit on
  139. ;    one line without overflow is equal to the size of the
  140. ;    line minus (SYMSIZ+2) divided by 5.  Example: if the
  141. ;    line size is 132 characters and SYMSIZ equals 8,
  142. ;    then Total num of ref/line can be INT((132-(8+2))/5)
  143. ;    or INT(122/5) or 20.
  144.  
  145. ;Symbol size is set by SYMSIZ.  This is the symbol size that the
  146. ;    program will use in the cross reference listing.  It
  147. ;    should be large enough to make each symbol unique in
  148. ;    cross reference listing.  If a symbol is larger than the
  149. ;    value for SYMSIZ, then the symbol will be truncated in the
  150. ;    output(eg: LARGE$SYMBOL would be LARGE$SYM if SYMSIZ was
  151. ;    set to 9.  Recommended value is 8.
  152.  
  153. ;OUTSECT sets the number of disk records that will be written to
  154. ;    disk when the output disk buffer is full.  This value is
  155. ;    used by the program to calculate the size of the output
  156. ;    disk buffer.  Output buffer size = OUTSECT * 128.
  157. ;    Recommended value is from 8 to 32.  16 works well.
  158.  
  159. ;INSECT is the number of disk records that will be read when the
  160. ;    disk input buffer is empty.  It is used to calculate the
  161. ;    size of the input buffer.  Input buffer size = INSECT * 128.
  162. ;    Recommend value is from 8 to 32.  16 works well.
  163.  
  164. ;NOTE:    If OUTSECT and INSECT are made too large, there will not be
  165. ;    be enough memory left to build the cross reference table
  166. ;    for a large program.  Largest tested values so far(3/6/82)
  167. ;    is 64 for OUTSECT and 64 for INSECT on a 64K system.  The
  168. ;    file successfully cross referenced was MODEM74.PRN. (JRM)
  169.  
  170. ;Graceful exit after error message if file not found
  171.  
  172. LPAGE    EQU    00        ;NUM LINES PER PAGE IF PEJECT IS TRUE
  173. NREFS    EQU    03        ;NUMBER OF REFERENCES PER REF TBL ENTRY
  174. LREFS    EQU    21        ;REFERENCES PER OUTPUT LINE
  175. SYMSIZ    EQU    08        ;NUMBER OF SYMBOL CHAR
  176. OUTSECT    EQU    32        ;NUMBER OF DISK SECTORS WRITTEN FROM BUFFER
  177. INSECT    EQU    32        ;NUMBER OF DISK SECTORS READ INTO BUFFER
  178.  
  179. ;********************************;
  180. ;
  181. ;       INTEL ASSEMBLER
  182. ;    CROSS REFERENCE PROGRAM  
  183. ;
  184. ;        VERSION 1.41
  185. ;
  186. ;       JEFF KRAVITZ 
  187. ;
  188. ;    MODIFIED BY JOHN MAHR
  189. ;
  190. ;********************************;
  191.  
  192. ;********************************;
  193. ;
  194. ;          MAIN LOOP
  195. ;
  196. ;********************************;
  197.     ORG    100H        ;ORIGIN ADDRESS
  198. XREF:    LXI    SP,STACK    ;SET STACK POINTER
  199.     CALL    SETUP        ;INITIALIZE
  200. MAIN:    CALL    GETBT        ;GET A BYTE FROM SOURCE FILE
  201.     CALL    SAVBT        ;SAVE BYTE IN PRINT BUFFER
  202. MAIN2:    CALL    CKNUM        ;TEST FOR NUMERIC
  203.     JNC    LNUM        ;YES, FOUND A NUMBER, PROCESS
  204.     CALL    CKALP        ;TEST FOR ALPHABETIC
  205.     JNC    LALPH        ;YES, PROCESS
  206.     LXI    H,CTAB1        ;POINT TO CHARACTER TABLE
  207.     CALL    LOOK        ;LOOK UP CHAR IN CHAR TABLE
  208.     JC    LIGN        ;NOT FOUND, IGNORE
  209.     PCHL            ;EXECUTE ROUTINE
  210.  
  211. ;*******************************************************
  212. ;
  213. ;        DONE
  214. ;
  215. ;      FINAL SYMBOL TABLE PRINT
  216. ;
  217. ; DONE gets control when a control Z(1AH) is found
  218. ; in the input data stream.  This routine:
  219. ;
  220. ;    1. issues a page eject
  221. ;    2. prints the cross reference table
  222. ;    3. issues a page eject
  223. ;    4. if disk output, writes out the remaining
  224. ;        sectors in the disk output buffer and
  225. ;        then closes the disk output file.
  226. ;    5. close the disk input file.
  227. ;    6. displays end of program message.
  228. ;
  229. ;*******************************************************
  230.  
  231. DONE:    CALL    EJECT        ;ISSUE PAGE EJECT
  232.     LHLD    SYMBT        ;GET SYMBOL TABLE BOTTOM
  233.     MVI    A,0FFH        ;check to see if there were...
  234.     CMP    M        ;...any symbols in the program
  235.     JZ    DLP4        ;no, don't print symbol table
  236.     SHLD    SYM        ;SET SYMBOL POINTER
  237.     LHLD    SYMTP        ;GET SYMBOL TABLE TOP
  238.     MVI    M,0FFH        ;END OFF SYMBOL TABLE
  239. DLP1:    LHLD    SYM        ;GET SYMBOL TABLE POINTER
  240.     CALL    PSYM        ;PRINT SYMBOL
  241.     LHLD    SYM
  242.     LXI    D,SYMSIZ+1    ;OFFSET TO REF LINK
  243.     DAD    D
  244.     MOV    E,M
  245.     INX    H
  246.     MOV    D,M        ;GET REF BLOCK ADDR
  247.     XCHG            ;INTO HL
  248.     SHLD    REF
  249.     CALL    PREFS        ;PRINT REFERENCES
  250.     LHLD    SYM        ;GET SYMBOL TABLE POINTER
  251.     LXI    D,SSIZ        ;SIZE OF SYM TABLE ENTRY
  252.     DAD    D
  253.     SHLD    SYM
  254.     MOV    A,M        ;GET BYTE
  255.     CPI    0FFH        ;END OF TABLE?
  256.     JNZ    DLP1        ;LOOP
  257.  
  258. DLP2:    CALL    EJECT        ;PAGE EJECT
  259.     LDA    DISKOUT        ;GET DISK OUTPUT SWITCH
  260.     ORA    A        ;DISK OUTPUT BEING USED?
  261.     JZ    DLP3        ;NO, ISSUE END MSG & RETURN TO CPM
  262.     LXI    H,DISKBUF    ;GET OUTPUT DISK BUFFER
  263.     LXI    D,OFCB        ;AND OUT FCB
  264.     CALL    DCLOSE        ;AND CLOSE OUTPUT DISK FILE
  265.  
  266. DLP3:    LXI    D,TFCB        ;CLOSE THE...
  267.     MVI    C,CLOSE        ;...INPUT...
  268.     CALL    CPM        ;...FILE.
  269.     LXI    D,DONEMSG    ;TELL OPERATOR...
  270.     MVI    C,PSTRING    ;...THAT PGM IS...
  271.     CALL    CPM        ;...DONE
  272.     JMP    BOOT        ;AND RETURN TO CP/M
  273.  
  274. DLP4:    LXI    H,NOSYMS    ;get no symbol message
  275.     MVI    B,28        ;NUMBER OF CHAR IN MSG
  276. DLP5:    MOV    E,M        ;print the...
  277.     CALL    PBYT        ;...message
  278.     INX    H
  279.     DCR    B
  280.     JNZ    DLP5
  281.     JMP    DLP2        ;go close files
  282.  
  283.  
  284.  
  285. ;********************************;
  286. ;
  287. ;     SYMBOL PRINT ROUTINE
  288. ;
  289. ;********************************;
  290. PSYM:    MVI    B,SYMSIZ    ;SYMBOL SIZE
  291. PSYM2:    MOV    E,M        ;GET BYTE
  292.     CALL    PBYT        ;PRINT BYTE
  293.     INX    H
  294.     DCR    B
  295.     JNZ    PSYM2
  296.     MVI    E,' '
  297.     CALL    PBYT        ;PRINT 2 SPACES
  298.     CALL    PBYT
  299.     RET
  300.  
  301. ;********************************;
  302. ;
  303. ;     REFERENCE PRINT ROUTINE
  304. ;
  305. ;********************************;
  306. PREFS:    MVI    A,LREFS/NREFS    ;NUMBER OF BLOCKS TO PRINT ON ONE LINE
  307.     STA    NLINS        ;TO NLINS
  308. PREF0:    LHLD    REF        ;GET REF BLOCK ADDR
  309.     INX    H
  310.     INX    H        ;BUMP TO FIRST REF NUMBER
  311.     SHLD    TEMP        ;SAVE REF NUM ADDR
  312.     MVI    A,(REFSZ-2)/2    ;NUMBER OF REF SLOTS
  313.     STA    SYMCT        ;SAVE IN SYMCT
  314. PREF:    LHLD    TEMP        ;GET REF SLOT ADDR
  315.     MOV    E,M
  316.     INX    H
  317.     MOV    D,M        ;GET REF
  318.     LXI    H,0000        ;ZERO?
  319.     CALL    CPHL
  320.     JZ    CRLF        ;YES, DONE
  321.     XCHG            ;GET NUM IN HL
  322.     CALL    DECOT        ;CONVERT
  323.     LXI    H,DEC        ;POINT TO DEC STRING
  324.     MVI    M,' '        ;BLANK LEADING ZERO
  325.     MVI    B,5        ;NUMBER OF DIGITS + 1 IN REF NUM
  326. PREF2:    MOV    E,M
  327.     CALL    PBYT        ;PRINT BYTE
  328.     INX    H
  329.     DCR    B
  330.     JNZ    PREF2        ;PRINT REFERENCE NUMBER
  331.     LHLD    TEMP        ;GET REF SLOT ADDR
  332.     INX    H
  333.     INX    H        ;BUMP TO NEXT SLOT
  334.     SHLD    TEMP
  335.     LDA    SYMCT        ;GET COUNT
  336.     DCR    A        ;DECREMENT
  337.     STA    SYMCT
  338.     JNZ    PREF
  339.     LHLD    REF        ;GET REF BLOCK ADDRESS
  340.     MOV    E,M
  341.     INX    H
  342.     MOV    D,M        ;GET LINK TO NEXT BLOCK
  343.     LXI    H,0000
  344.     CALL    CPHL        ;ANY MORE BLOCKS?
  345.     JZ    CRLF        ;NO, EXIT
  346.     XCHG            ;YES, SET NEXT BLOCK POINTER IN REF
  347.     SHLD    REF
  348.     LDA    NLINS
  349.     DCR    A        ;DECREMENT LINES COUNT
  350.     STA    NLINS
  351.     JNZ    PREF0        ;AND PRINT MORE ON SAME LINE
  352.     CALL    CRLF        ;PRINT CR,LF
  353.     MVI    B,SYMSIZ+2    ;INDENT CONTINUATION LINE...
  354. PREF3:    MVI    E,' '        ;...WITH SPACES
  355.     CALL    PBYT        ;PRINT SPACES
  356.     DCR    B
  357.     JNZ    PREF3        ;PRINT 6 SPACES
  358.     JMP    PREFS
  359.  
  360. ;********************************;
  361. ;
  362. ;   CHARACTER PARSING ROUTINES
  363. ;
  364. ;********************************;
  365. LALPH:    LXI    H,SBUF        ;POINT TO SYMBOL BUFFER
  366.     MVI    C,SYMSIZ
  367.     MVI    A,' '        ;FILL SYMBOL...
  368. LALX:    MOV    M,A        ;...WITH...
  369.     INX    H        ;...BLANKS
  370.     DCR    C
  371.     JNZ    LALX        ;CLEAR SYMBOL BUFFER
  372.     LXI    H,SBUF
  373.     SHLD    SYMPT
  374.     MVI    A,00
  375.     STA    SYMCT        ;RESET SYMBOL POINTER+COUNT
  376.     LDA    CHAR        ;GET CHARACTER AGAIN
  377.     CALL    GTSYM        ;COLLECT IDENTIFIER
  378. LALC:    CALL    GETBT        ;GET A BYTE FROM SOURCE FILE
  379.     CALL    SAVBT        ;SAVE BYTE IN PRINT BUFFER
  380.     CALL    CKNUM        ;TEST FOR NUMBER
  381.     JNC    LAL3        ;YES, CONTINUE
  382.     CALL    CKALP        ;TEST FOR ALPHABETIC
  383.     JNC    LAL3        ;YES, CONTINUE
  384.     CALL    CRES        ;TEST FOR RESERVED WORD
  385.     JC    LAL1        ;NO, CONTINUE
  386. LAL0:    LDA    CHAR        ;GET CHARACTER THAT ENDED ID
  387.     JMP    MAIN2        ;CONTINUE SCAN
  388. LAL1:    CALL    FIND        ;SEE IF DEFINED
  389.     JC    LAL2        ;NO, CONTINUE
  390.     CALL    ADDRF        ;YES, ADD REFERENCE
  391.     JMP    LAL0        ;DONE
  392. LAL2:    CALL    ENSYM        ;ENTER SYMBOL DEFINITION
  393.     CALL    ADDRF        ;ADD REFERENCE
  394.     JMP    LAL0        ;CONTINUE
  395. LAL3:    CALL    GTSYM        ;COLLECT IDENTIFIER
  396.     JMP    LALC        ;CONTINUE
  397.  
  398. LNUM:    CALL    GETBT        ;GET BYTE
  399.     CALL    SAVBT        ;SAVE BYTE IN PRINTER BUFFER
  400.     CALL    CKNUM        ;TEST FOR NUMERIC
  401.     JNC    LNUM        ;YES, CONTINUE
  402.     CALL    CKALP        ;TEST FOR ALPHABETIC
  403.     JNC    LNUM        ;YES, CONTINUE
  404.     JMP    MAIN2        ;CONTINUE WITH MAIN SCAN
  405.  
  406. LQUOT:    CALL    GETBT        ;GET A BYTE
  407.     CALL    SAVBT        ;SAVE BYTE IN PRINTER BUFFER
  408.     CPI    ''''        ;SEE IF STRING QUOTE
  409.     JNZ    LQUOT        ;NO, KEEP LOOPING
  410.     CALL    GETBT        ;GET NEXT BYTE
  411.     CALL    SAVBT        ;SAVE BYTE
  412.     CPI    ''''        ;TEST FOR DOUBLES
  413.     JZ    LQUOT        ;YES, START SCAN AGAIN
  414.     JMP    MAIN2        ;NO, CONTINUE IN MAIN SCAN
  415.  
  416. LSEMI:    CALL    GETBT        ;GET A BYTE
  417.     CALL    SAVBT        ;SAVE BYTE
  418.     CPI    0DH        ;WAIT FOR CR
  419.     JNZ    LSEMI        ;CONTINUE
  420.     JMP    MAIN2        ;ENTER MAIN LOOP
  421.  
  422. LCR:    CALL    PLINE        ;PRINT LINE
  423.     LHLD    LCNT        ;GET LINE NUMBER
  424.     INX    H        ;BUMP LINE NUMBER
  425.     SHLD    LCNT        ;STORE
  426.     JMP    MAIN
  427.  
  428. LLF:    PUSH    PSW        ;save char
  429.     LDA    FTPRN        ;is it file...
  430.     ORA    A        ;...type PRN?
  431.     JZ    LLF2        ;yes, skip 1rst 16 char
  432.     POP    PSW        ;restore char
  433.     JMP    MAIN
  434.  
  435. LLF2:    POP    PSW        ;RESTORE CHARACTER
  436.     MVI    B,16        ;# OF CHAR TO SKIP OVER
  437.  
  438. LLF3:    CALL    GETBT        ;get next byte
  439.     CALL    SAVBT        ;put in print buf
  440.     CPI    0DH        ;carriage return?
  441.     JZ    LCR        ;yes, get next line
  442.     DCR    B        ;skipped all char?
  443.     JNZ    LLF3        ;no, continue skipping
  444.     JMP    MAIN        ;CONTINUE
  445.  
  446. LIGN:    JMP    MAIN        ;RE-ENTER MAIN LOOP
  447.  
  448. LSPC    EQU    LIGN
  449. LTAB    EQU    LIGN
  450. LDOL    EQU    LIGN
  451. LDEL    EQU    LIGN
  452.  
  453. ;********************************;
  454. ;
  455. ;          SUBROUTINES
  456. ;
  457. ;********************************;
  458.  
  459. ;******************************************************************
  460. ;
  461. ;        SETUP
  462. ;
  463. ;         INITIALIZATION
  464. ;
  465. ; 1. displays program logo and version
  466. ; 2. checks for input file type PRN.
  467. ;    -if file type PRN, sets PRN switch.
  468. ; 3. if oper specified FN.FT CON, then sets console
  469. ;    output switch on.  Goes to step 5.
  470. ; 4. else check for disk output option.
  471. ;    -if not disk output, default to printer output.
  472. ;        -go to step 5.
  473. ;    -else check to see if cross reference file exists.
  474. ;        -if it exists, ask operater if it is to
  475. ;         be erased.
  476. ;            -if no erase, terminate program
  477. ;            -else erase cross reference file.
  478. ;    -then create new cross reference disk file.
  479. ;    -initialize output character pointer to disk buffer.
  480. ; 5. open input disk file.
  481. ; 6. initialize printer buffer, address pointers for symbol table
  482. ;    and reference table, set line counter to 1.
  483. ; 7. return to caller
  484. ;
  485. ;******************************************************************
  486.  
  487. SETUP:    LXI    D,LOGO        ;get program logo msg
  488.     MVI    C,PSTRING    ;BDOS PRINT STRING
  489.     CALL    CPM        ;PRINT LOGO
  490.     LDA    TFCB+1        ;get first char of file name
  491.     CPI    '?'        ;help function?
  492.     JNZ    SETUP1        ;no, go check input file type
  493.     LXI    D,HELP        ;display help message
  494.     JMP    FERR1
  495.  
  496. SETUP1:    LDA    TFCB+9        ;get first char of file type
  497.     CPI    'P'        ;is it type PRN?
  498.     JNZ    SETUP2        ;no, don't set switch
  499.     LDA    TFCB+10        ;get 2nd char of file type
  500.     CPI    'R'
  501.     JNZ    SETUP2
  502.     LDA    TFCB+11        ;get 3rd char of file type
  503.     CPI    'N'
  504.     JNZ    SETUP2
  505.     XRA    A
  506.     STA    FTPRN        ;turn on prn file type
  507.  
  508. SETUP2:    LDA    TFCB+17        ;get 1rst char of 2nd fcb
  509.     CPI    'C'        ;output to console?
  510.     JNZ    SETUP3        ;no, don't turn on switch
  511.     LDA    TFCB+18        ;get 2nd char of 2nd fcb
  512.     CPI    'O'        ;output to console?
  513.     JNZ    SETUP3        ;no, don't turn on switch
  514.     MVI    A,0FFH        ;turn on...
  515.     STA    CONSOLE        ;...console output
  516.     JMP    SETUP6        ;go open input file
  517. SETUP3:    LDA    TFCB+17        ;get 1rst char of 2nd fcb
  518.     CPI    'D'        ;output to be written to disk?
  519.     JNZ    SETUP6        ;no, go open input file.
  520.     STA    DISKOUT        ;turn on disk output switch
  521.     LDA    TFCB+16        ;get output file drive number
  522.     STA    OFCB        ;move to output fcb
  523.     LXI    D,TFCB        ;point to fcb
  524.     CALL    FOPEN        ;open disk input file
  525.     LXI    D,TFCB+1    ;point to input file name
  526.     MVI    B,8        ;length of file name
  527.     LXI    H,OFCB+1    ;point to output fcb file name
  528.     CALL    MOVE        ;move input file name to output fcb
  529.     LXI    D,OFCB        ;does output file...
  530.     MVI    C,OPEN        ;...already...
  531.     CALL    CPM        ;...exist?
  532.     CPI    0FFH        ;open succeed?
  533.     JZ    SETUP4        ;no, file does not exist
  534.     LXI    D,OFCB        ;close...
  535.     MVI    C,CLOSE        ;...the open...
  536.     CALL    CPM        ;...file.
  537.     LXI    D,MSG1        ;ask operator...
  538.     MVI    C,PSTRING    ;...if old file...
  539.     CALL    CPM        ;...is to be...
  540.     MVI    C,CONIN        ;...deleted
  541.     CALL    CPM
  542.     ANI    05FH        ;make upper case
  543.     CPI    'Y'        ;operator say yes?
  544.     JNZ    BOOT        ;no, terminate
  545.     LXI    D,CONCRLF    ;write carriage return...
  546.     MVI    C,PSTRING    ;...line feed to console
  547.     CALL    CPM
  548.     LXI    D,OFCB        ;point to fcb to delete file
  549.     MVI    C,DELETE    ;delete the...
  550.     CALL    CPM        ;...file
  551.     CPI    0FFH        ;delete succeed?
  552.     LXI    D,EMSG2        ;get err msg in case of failure
  553.     JZ    FERR1        ;failure, print msg & quit
  554.  
  555. SETUP4:    LXI    D,OFCB        ;point to output fcb
  556.     MVI    C,MAKE        ;create new...
  557.     CALL    CPM        ;...cross reference file.
  558.     CPI    0FFH        ;create succeed?
  559.     LXI    D,EMSG3        ;get err msg in case of failure
  560.     JZ    FERR1        ;create failed, print msg & quit
  561.     LXI    H,DISKBUF    ;get addr of disk buffer
  562.     SHLD    DCHAR        ;init disk char pointer
  563.  
  564. SETUP6:    LXI    D,TFCB        ;POINT TO FCB
  565.     CALL    FOPEN        ;OPEN FCB
  566.     LXI    H,PBUF
  567.     SHLD    LPNT        ;SET PRINT POINTER
  568.     LXI    H,00001        ;SET LINE COUNTER...
  569.     SHLD    LCNT        ;...TO ONE.
  570.     LXI    H,SYMT        ;GET ADDRESS OF SYMBOL TABLE
  571.     SHLD    SYM
  572.     SHLD    SYMBT
  573.     SHLD    SYMTP        ;SET SYMBOL TABLE POINTERS
  574.     LHLD    MEMSZ        ;GET AVAILABLE MEMORY ADDRESS
  575.     DCX    H
  576.     SHLD    REF
  577.     SHLD    REFBT
  578.     SHLD    REFTP        ;SET REFERENCE TABLE POINTERS
  579.     RET
  580.  
  581. ;********************************;
  582. ;
  583. ;    CHECK FOR RESERVED WORD
  584. ;
  585. ;********************************;
  586. CRES:    LXI    H,RTAB        ;POINT TO RESERVED WORD TABLE
  587.     SHLD    TEMP        ;SAVE IN TEMP WORD
  588. CRES1:    LHLD    TEMP        ;GET TABLE POINTER
  589.     LXI    D,SBUF        ;POINT TO SYMBOL
  590.     MVI    B,5        ;SYMBOL SIZE
  591. CRES2:    LDAX    D        ;GET SYMBOL BYTE
  592.     CMP    M        ;COMPARE AGAINST TABLE ENTRY
  593.     RC            ;LESS, NOT IN TABLE
  594.     JNZ    CRES3        ;GREATER, GET NEXT TABLE ENTRY
  595.     INX    D        ;BUMP POINTERS
  596.     INX    H
  597.     DCR    B        ;DECREMENT BYTE COUNT
  598.     JNZ    CRES2        ;KEEP TESTING
  599.     JMP    CRES4        ;FOUND
  600. CRES3:    LHLD    TEMP        ;GET TABLE POINTER
  601.     LXI    D,RSIZ        ;SIZE OF ENTRY
  602.     DAD    D        ;BUMP POINTER
  603.     SHLD    TEMP        ;STORE NEW POINTER
  604.     MOV    A,M        ;GET TABLE BYTE
  605.     CPI    0FFH        ;END OF TABLE?
  606.     JNZ    CRES1        ;NO, LOOP
  607.     STC            ;SET CARRY (NOT IN TABLE)
  608.     RET
  609. CRES4:    ORA    A        ;RESET CARRY
  610.     RET
  611.  
  612. ;********************************;
  613. ;
  614. ;     FIND SYMBOL IN TABLE
  615. ;
  616. ;********************************;
  617. FIND:    LHLD    SYMBT        ;GET BEGIN OF SYM TABLE
  618.     SHLD    SYM        ;SET TEMP POINTER
  619. FIND1:    LHLD    SYM        ;GET TEMP POINTER
  620.     LXI    D,SBUF        ;POINT TO CURRENT SYMBOL
  621.     MVI    B,SYMSIZ    ;SYMBOL SIZE
  622. FIND2:    LDAX    D        ;GET BYTE FROM SBUF
  623.     CMP    M        ;COMPARE TO SYM TABLE BYTE
  624.     RC            ;GREATER, NOT IN TABLE
  625.     JNZ    FIND3        ;LESS, GET NEXT TABLE ENTRY
  626.     INX    D        ;BUMP POINTER
  627.     INX    H        ;BUMP POINTER
  628.     DCR    B        ;DECREMENT BYTE COUNT
  629.     JNZ    FIND2        ;LOOP
  630.     RET            ;TRUE ZERO, FOUND
  631. FIND3:    LHLD    SYM        ;GET CURRENT POINTER
  632.     LXI    D,SSIZ        ;SYMBOL TABLE ENTRY SIZE
  633.     DAD    D        ;BUMP POINTER
  634.     XCHG            ;INTO DE
  635.     LHLD    SYMTP        ;GET TOP OF SYMBOL TABLE
  636.     CALL    CPHL        ;TEST FOR END OF TABLE
  637.     JZ    FIND4        ;YES, DONE
  638.     JC    FERR        ;TABLE OVERFLOW, ERROR
  639.     XCHG            ;CURRENT POINTER INTO HL
  640.     SHLD    SYM        ;SET CURRENT POINTER
  641.     JMP    FIND1        ;LOOP
  642. FIND4:    STC            ;SET CARRY FOR NOT FOUND
  643.     LHLD    SYMTP        ;GET CURRENT TOP
  644.     SHLD    SYM        ;SET CURRENT POINTER
  645.     RET
  646.  
  647. FERR:    LXI    D,EMSG1        ;SYMBOL TABLE ERR MSG
  648.  
  649. FERR1:    MVI    C,PSTRING    ;WRITE CONSOLE
  650.     CALL    CPM        ;ISSUE ERROR MESSAGE
  651.     JMP    BOOT        ;EXIT
  652.  
  653. FERR2:    LXI    D,EMSG6        ;no room for symbol table
  654.     JMP    FERR1
  655.  
  656. ;********************************;
  657. ;
  658. ;   ADD REFERENCE TO REF TABLE
  659. ;
  660. ;********************************;
  661. ADDRF:    LHLD    SYM        ;GET SYMBOL POINTER
  662.     LXI    D,SYMSIZ+1    ;OFFSET PAST SYMBOL&FLAGS
  663.     DAD    D
  664.     MOV    E,M
  665.     INX    H
  666.     MOV    D,M        ;GET REFERENCE POINTER
  667.     LXI    H,0000
  668.     CALL    CPHL        ;TEST FOR ZERO REF PTR
  669.     JZ    BLDRF        ;YES, BUILD REFERENCE ENTRY
  670. LINK1:    XCHG            ;REF PTR IN HL
  671.     MOV    E,M        ;GET REF LINK
  672.     INX    H
  673.     MOV    D,M        ;INTO DE
  674.     DCX    H        ;REPOSITION HL
  675.     PUSH    H        ;SAVE REF PTR
  676.     LXI    H,0000
  677.     CALL    CPHL        ;IF LINK IS ZERO
  678.     POP    H
  679.     JNZ    LINK1        ;NON ZERO, GET NEXT LINK
  680.     SHLD    REF        ;SAVE REF POINTER
  681.     INX    H
  682.     INX    H        ;SKIP TO FIRST REF NUMBER
  683.     MVI    B,(REFSZ-2)/2    ;NUMBER OF REF NUMBERS/ENTRY
  684. LINK3:    MOV    E,M        ;GET REF NUMBER
  685.     INX    H
  686.     MOV    D,M
  687.     DCX    H        ;REPOSITION
  688.     PUSH    H        ;SAVE REF NUM ADDR
  689.     LXI    H,0000
  690.     CALL    CPHL        ;SEE IF REF NUM IS ZERO
  691.     POP    H
  692.     JZ    ENREF        ;YES, ENTER REFERENCE
  693.     INX    H
  694.     INX    H        ;SKIP TO NEXT REF NUM
  695.     DCR    B        ;DECREMENT COUNT
  696.     JNZ    LINK3        ;TRY AGAIN AT NEXT SLOT
  697.     CALL    ADBLK        ;ADD NEW REF BLOCK
  698.     LHLD    REF        ;GET REF POINTER
  699.     INX    H
  700.     INX    H        ;SKIP TO FIRST REF SLOT
  701. ENREF:    PUSH    H        ;SAVE REF SLOT ADDR
  702.     LHLD    LCNT        ;GET LINE NUMBER
  703.     XCHG            ;INTO DE
  704.     POP    H        ;GET REF SLOT ADDR
  705.     MOV    M,E
  706.     INX    H
  707.     MOV    M,D        ;STORE LINE REF
  708.     RET            ;DONE
  709. ;********************************;
  710. ;
  711. ;     BUILD REF TABLE BLOCK
  712. ;
  713. ;********************************;
  714. BLDRF:    LHLD    SYM        ;GET SYMBOL POINTER
  715.     LXI    D,SYMSIZ+1    ;OFFSET TO REF POINTER
  716.     DAD    D
  717.     SHLD    REF        ;SET TEMP REF POINTER TO HERE
  718.     CALL    ADBLK        ;ADD BLOCK
  719.     LHLD    REF        ;GET REAL REF POINTER
  720.     INX    H
  721.     INX    H        ;POSITION TO FIRST REF SLOT
  722.     JMP    ENREF        ;ADD REFERENCE
  723. ADBLK:    LHLD    REFBT        ;GET REF BOTTOM
  724.     LXI    D,REFSZ        ;SUBTRACT REF SIZE
  725.     MOV    A,L
  726.     SUB    E
  727.     MOV    L,A
  728.     MOV    A,H
  729.     SBB    D
  730.     MOV    H,A
  731.     SHLD    TEMP        ;SAVE NEW REF BOTTOM
  732.     XCHG            ;INTO DE ALSO
  733.     LHLD    SYMTP        ;GET SYMBOL TOP
  734.     CALL    CPHL        ;CHECK FOR BUMP
  735.     JZ    FERR2        ;YES, NO ROOM
  736.     JNC    FERR2        ;NO ROOM
  737.     LHLD    TEMP        ;GET REF BOTTOM
  738.     XCHG            ;INTO DE
  739.     LHLD    REF        ;GET REF POINTER
  740.     MOV    M,E        ;SET LINK
  741.     INX    H
  742.     MOV    M,D        ;TO NEW REF BLOCK
  743.     LHLD    TEMP        ;GET NEW REF BLOCK ADDR
  744.     SHLD    REF        ;STORE IN REF
  745.     MVI    B,REFSZ        ;SIZE OF REF BLOCK
  746.     MVI    A,00
  747. ADB2:    MOV    M,A        ;ZERO THE REF BLOCK
  748.     INX    H
  749.     DCR    B
  750.     JNZ    ADB2
  751.     LHLD    TEMP        ;GET NEW REF BOTTOM
  752.     SHLD    REFBT        ;SET REFBT
  753.     RET
  754.  
  755. ;********************************;
  756. ;
  757. ;     ENTER SYMBOL IN SYM TABLE
  758. ;
  759. ;********************************;
  760. ENSYM:    LHLD    SYM        ;GET SYMBOL POINTER
  761.     XCHG            ;INTO DE
  762.     LHLD    SYMTP        ;GET SYMBOL TABLE TOP
  763.     CALL    CPHL        ;CHECK FOR END OF TABLE
  764.     JZ    NWSYM        ;YES, ADD SYMBOL AT END
  765.     LXI    D,SSIZ        ;SYMBOL TABLE ENTRY SIZE
  766.     DAD    D        ;CALCULATE NEW END OF TABLE
  767.     XCHG            ;INTO DE
  768.     LHLD    REFBT        ;REFERENCE TABLE BOTTOM
  769.     CALL    CPHL        ;TEST FOR TABLE OVERFLOW
  770.     LXI    D,EMSG7        ;ADDR OF ERR MSG IN OF OVERFLOW
  771.     JZ    FERR1        ;FULL, ERROR
  772.     JC    FERR1        ;YES, ERROR
  773.     LHLD    SYMTP        ;GET TABLE TOP
  774.     LXI    D,SSIZ-1    ;BUMP TO END OF ENTRY
  775.     DAD    D
  776.     SHLD    TO        ;STORE IN TO ADDRESS
  777.     LXI    D,SSIZ
  778.     MOV    A,L
  779.     SUB    E
  780.     MOV    L,A
  781.     MOV    A,H
  782.     SBB    D
  783.     MOV    H,A        ;SUBTRACT SIZE OF ONE ENTRY
  784.     SHLD    FROM        ;STORE AS FROM ADDRESS
  785.     LHLD    SYM        ;GET CURRENT POINTER
  786.     SHLD    LIMIT        ;STORE AS LIMIT ADDRESS
  787.     CALL    MVUP        ;MOVE TABLE UP IN MEMORY
  788. NWSYM:    LHLD    SYM        ;GET CURRENT POINTER
  789.     LXI    D,SBUF        ;POINT TO SYMBOL
  790.     MVI    B,SYMSIZ    ;SIZE OF SYMBOL
  791.     CALL    MOVE        ;COPY SYMBOL TO TABLE
  792.     MVI    A,0
  793.     MOV    M,A
  794.     INX    H
  795.     MOV    M,A
  796.     INX    H
  797.     MOV    M,A        ;SET POINTERS TO 0000
  798.     LHLD    SYMTP        ;GET SYMBOL TABLE TOP
  799.     LXI    D,SSIZ        ;GET SYMBOL ENTRY SIZE
  800.     DAD    D        ;BUMP
  801.     SHLD    SYMTP        ;STORE EW TOP
  802.     RET
  803.  
  804. ;********************************;
  805. ;
  806. ;    MOVE SYMBOL TABLE UP
  807. ;
  808. ;********************************;
  809. MVUP:    LHLD    TO        ;GET TO POINTER
  810.     MOV    B,H
  811.     MOV    C,L        ;INTO BC
  812.     LHLD    FROM        ;GET FROM POINTER
  813.     XCHG            ;INTO DE
  814.     LHLD    LIMIT        ;GET LIMIT ADDRESS
  815. MVUP2:    LDAX    D        ;GET FROM BYTE
  816.     STAX    B        ;STORE AT TO ADDRESS
  817.     CALL    CPHL        ;COMPARE FROM TO LIMIT
  818.     RZ            ;EXIT IF DONE
  819.     DCX    B        ;DECREMENT TO
  820.     DCX    D        ;DECRMENT FROM
  821.     JMP    MVUP2        ;LOOP
  822.  
  823. ;********************************;
  824. ;
  825. ;  GENERAL PURPOSE MOVE ROUTINE
  826. ;
  827. ;********************************;
  828. MOVE:    LDAX    D        ;GET BYTE
  829.     MOV    M,A        ;STORE BYTE
  830.     INX    D
  831.     INX    H        ;BUMP POINTERS
  832.     DCR    B        ;DECREMENT COUNT
  833.     JNZ    MOVE        ;LOOP
  834.     RET
  835.  
  836. ;********************************;
  837. ;
  838. ;    BINARY TO DECIMAL CONVERSION
  839. ;
  840. ;********************************;
  841. DECOT:    LXI    D,DEC
  842.     XCHG
  843.     LXI    B,10000
  844.     CALL    DIG
  845.     LXI    B,1000
  846.     CALL    DIG
  847.     LXI    B,100
  848.     CALL    DIG
  849.     LXI    B,10
  850.     CALL    DIG
  851.     LXI    B,1
  852.     CALL    DIG
  853.     RET
  854.  
  855. DIG:    MVI    M,'0'
  856. DI0:    MOV    A,E
  857.     SUB    C
  858.     MOV    E,A
  859.     MOV    A,D
  860.     SBB    B
  861.     MOV    D,A
  862.     JM    DI2
  863.     INR    M
  864.     JMP    DI0
  865. DI2:    MOV    A,E
  866.     ADD    C
  867.     MOV    E,A
  868.     MOV    A,D
  869.     ADC    B
  870.     MOV    D,A
  871.     INX    H
  872.     RET
  873.  
  874. ;********************************;
  875. ;
  876. ;    TEST FOR ALPHABETIC CHAR.
  877. ;
  878. ;********************************;
  879. CKALP:    cpi    '$'        ;treat '$' like a char
  880.     rz
  881.  
  882.     CPI    'A'        ;ASCII 'A'
  883.     RC            ;NO, EXIT
  884.     CPI    'Z'+1
  885.     CMC
  886.     RET
  887.  
  888. ;********************************;
  889. ;
  890. ;       TEST FOR NUMERIC CHAR
  891. ;
  892. ;********************************;
  893. CKNUM:    CPI    '0'
  894.     RC
  895.     CPI    '9'+1
  896.     CMC
  897.     RET
  898.  
  899. ;********************************;
  900. ;
  901. ;  LOOK UP CHAR IN PARSE TABLE
  902. ;
  903. ;********************************;
  904. LOOK:    LXI    D,0003        ;TABLE ENTRY SIZE
  905.     MOV    B,A        ;ARGUMENT BYTE IN B
  906. LOOK2:    MOV    A,M        ;GET TABLE BYTE
  907.     CPI    0FFH        ;END OF TABLE?
  908.     JZ    LOOKN        ;YES, NOT FOUND
  909.     CMP    B        ;COMPARE
  910.     JZ    LOOKY        ;FOUND
  911.     DAD    D        ;BUMP POINTER
  912.     JMP    LOOK2        ;LOOP
  913. LOOKN:    STC            ;CARRY = NOT FOUND
  914.     RET
  915.  
  916. LOOKY:    INX    H        ;SKIP TO TABLE BYTE
  917.     MOV    E,M
  918.     INX    H
  919.     MOV    D,M        ;TABLE ENTRY IN DE
  920.     XCHG            ;INTO HL
  921.     RET
  922.  
  923. ;********************************;
  924. ;
  925. ;    SAVE BYTE IN LINE BUFFER
  926. ;
  927. ;********************************;
  928. SAVBT:    LHLD    LPNT        ;GET LINE POINTER
  929.     MOV    M,A        ;SAVE BYTE
  930.     INX    H        ;BUMP POINTER
  931.     SHLD    LPNT        ;SAVE POINTER
  932.     call    lwrupr        ;convert lower to upper case
  933.     sta    char        ;save char in char
  934.     RET
  935.  
  936. ;********************************;
  937. ;
  938. ;  PRINT SOURCE LINE WITH NUMBER
  939. ;
  940. ;********************************;
  941. PLINE:    LHLD    LCNT        ;GET LINE NUMBER
  942.     CALL    DECOT        ;CONVERT TO DECIMAL
  943.     LXI    H,DEC        ;POINT TO DEC STRING
  944. PL2:    MOV    E,M        ;GET STRING BYTE
  945.     MOV    A,E
  946.     CPI    0DH        ;DONE?
  947.     JZ    PL3        ;YES
  948.     CALL    PBYT        ;PRINT BYTE
  949.     INX    H        ;BUMP POINTER
  950.     JMP    PL2
  951. PL3:    MVI    E,':'
  952.     CALL    PBYT        ;PRINT ':'
  953.     MVI    E,' '
  954.     CALL    PBYT        ;PRINT ' '
  955.     CALL    PBYT        ;PRINT SPACE
  956.     LXI    H,PBUF        ;POINT TO PRINT BUFFER
  957.     MVI    A,00
  958.     STA    COL        ;SET COLUMN COUNT
  959. PL41:    MOV    E,M        ;GET BYTE
  960.     MOV    A,E
  961.     CPI    0DH        ;DONE?
  962.     JZ    PL5
  963.     CPI    0AH        ;LF?
  964.     JZ    PL4A        ;YES, IGNORE
  965.     CPI    09H        ;TAB?
  966.     JNZ    PL42        ;NO, CONTINUE
  967.     PUSH    H        ;SAVE HL
  968. PL43:    MVI    E,' '
  969.     CALL    PBYT        ;PRINT SPACE
  970.     LXI    H,COL
  971.     INR    M
  972.     MOV    A,M
  973.     ANI    07H        ;MODULO 8
  974.     JNZ    PL43
  975.     POP    H
  976.     JMP    PL4A
  977. PL42:    LDA    COL
  978.     INR    A
  979.     STA    COL
  980.     CALL    PBYT        ;PRINT BYTE
  981. PL4A:    INX    H
  982.     JMP    PL41
  983. PL5:    CALL    CRLF        ;PRINT CR,LF
  984.     LXI    H,PBUF
  985.     SHLD    LPNT        ;RESET LINE POINTER
  986.     RET
  987.  
  988. ;********************************;
  989. ;
  990. ;      COLLECT SYMBOL IN SYM BUF
  991. ;
  992. ;********************************;
  993. GTSYM:    MOV    B,A        ;SAVE CHAR
  994.     LDA    SYMCT        ;GET SYMBOL COUNT
  995.     CPI    SYMSIZ        ;MAX?
  996.     RNC            ;YES, DONE 
  997.     INR    A
  998.     STA    SYMCT
  999.     LHLD    SYMPT
  1000.     MOV    M,B
  1001.     INX    H        ;BUMP SYMBOL POINTER
  1002.     SHLD    SYMPT
  1003.     RET
  1004.  
  1005. ;********************************;
  1006. ;
  1007. ;       PRINTER INTERFACES
  1008. ;
  1009. ;********************************;
  1010.  
  1011. ;********************************;
  1012. ;
  1013. ;       PRINT A SINGLE BYTE
  1014. ;
  1015. ;********************************;
  1016. PBYT:    PUSH    B
  1017.     PUSH    D
  1018.     PUSH    H
  1019.     PUSH    PSW
  1020.     LDA    DISKOUT        ;disk output...
  1021.     ORA    A        ;...in effect?
  1022.     JNZ    DBYT        ;yes, go write to disk
  1023.     MVI    C,05
  1024.     LDA    CONSOLE        ;get console out switch
  1025.     ORA    A        ;console output?
  1026.     JZ    PBYT2        ;no, print output
  1027.     MVI    C,2        ;console output
  1028.  
  1029. PBYT2:    CALL    CPM
  1030.  
  1031. PBYT3:    MVI    C,11        ;CHECK CONSOLE STATUS
  1032.     CALL    CPM
  1033.     ORA    A        ;IF ZERO, OK
  1034.     JZ    PBYTX        ;EXIT
  1035.     MVI    C,1
  1036.     CALL    CPM        ;READ CONSOLE CHAR
  1037.     CPI    3
  1038.     JZ    BOOT        ;ABORT IF ^C, OTHERWISE IGNORE
  1039. PBYTX:    POP    PSW
  1040.     POP    H
  1041.     POP    D
  1042.     POP    B
  1043.     RET
  1044.  
  1045. ;**************************************;
  1046. ;
  1047. ;        DBYT
  1048. ;
  1049. ;    PUT OUTPUT CHARACTER
  1050. ;    INTO DISK BUFFER.
  1051. ;        INPUT=E(OUTPUT CHAR)
  1052. ;
  1053. ; 1. move character to buffer.
  1054. ; 2. if at end of buffer, go
  1055. ;    write out disk buffer.
  1056. ; 3. else add 1 to disk buffer
  1057. ;    pointer.
  1058. ; 4. subtract 1 from number of
  1059. ;    positions left in buffer.
  1060. ; 5. go check if operator pressed
  1061. ;    control C.
  1062. ;
  1063. ;***************************************;
  1064.  
  1065. DBYT:    MOV    A,E        ;save char to be put in buffer
  1066.     LHLD    DSKCNT        ;get num of char left in buf
  1067.     XCHG            ;put num in D,E
  1068.     LHLD    DCHAR        ;point to next char in buf
  1069.     MOV    M,A        ;put char in disk buf
  1070.     DCR    E        ;at end of buf?
  1071.     JNZ    DBYT1        ;no, don't write buffer
  1072.     DCR    D        ;at end of buf?
  1073.     JZ    PUTREC        ;yes, go write buffer
  1074.  
  1075. DBYT1:    INX    H        ;point to next char in buf
  1076.     SHLD    DCHAR        ;save next pos
  1077.     XCHG            ;put num of char left in H,L
  1078.     SHLD    DSKCNT        ;save num of remaining char
  1079.     JMP    PBYT3        ;go check console status
  1080.  
  1081. ;****************************************************************
  1082. ;        PUTREC
  1083. ;    WRITE OUT DISK BUFFER TO DISK
  1084. ;
  1085. ;    1. initialize start of disk buffer address and number
  1086. ;        of sectors to write out.
  1087. ;    2. get current disk sector buffer address
  1088. ;    3. add 128 to it and save for DMA of sector after
  1089. ;        current sector.
  1090. ;    4. do DMA for current sector buffer address
  1091. ;    5. write current disk sector
  1092. ;    6. if not last sector repeat steps 2 thru 5.
  1093. ;    7. set number of characters positions left in buffer
  1094. ;        to size of buffer.
  1095. ;    8. set disk output buffer pointer to front of buffer.
  1096. ;    9. go check to see if operator pressed control C.
  1097. ;
  1098. ;***************************************************************
  1099. PUTREC:    LXI    H,DISKBUF    ;address of disk buffer
  1100.     SHLD    BUFADR        ;save it for later DMA's
  1101.     MVI    B,OUTSECT    ;number of disk sectors to write
  1102.  
  1103. PUTRC2:    PUSH    B        ;save sector count
  1104.     LHLD    BUFADR        ;get disk buffer address
  1105.     XCHG            ;put it in D,E for DMA
  1106.     LXI    H,80H        ;put 128 H,L
  1107.     DAD    D        ;add 128 to disk buf adr for next DMA
  1108.     SHLD    BUFADR        ;save it for next DMA
  1109.     MVI    C,SETDMA    ;point DMA to...
  1110.     CALL    CPM        ;...correct buffer
  1111.     LXI    D,OFCB        ;get output disk fcb
  1112.     MVI    C,WRITE        ;write sector...
  1113.     CALL    CPM        ;...to disk
  1114.     ORA    A        ;was write successfull?
  1115.     POP    B        ;restore num of sectors left
  1116.     LXI    D,EMSG4        ;get err msg in case write failed
  1117.     JNZ    FERR1        ;disk write failed, display err msg, quit
  1118.     DCR    B        ;written 16 sectors yet?
  1119.     JNZ    PUTRC2        ;no, continue writing disk sectors
  1120.     LXI    H,OUTSECT*128    ;put disk buffer size into H,L
  1121.     SHLD    DSKCNT        ;set num of char left in buf to buffer size
  1122.     LXI    H,DISKBUF    ;point to front...
  1123.     SHLD    DCHAR        ;...of disk buffer
  1124.     JMP    PBYT3        ;go check console status for ^C
  1125.  
  1126. ;*********************************;
  1127. ;
  1128. ;      ISSUE PAGE EJECT
  1129. ;
  1130. ;*********************************;
  1131. EJECT:    MVI    E,0CH        ;printer eject command
  1132.     CALL    PBYT
  1133.     MVI    E,00H
  1134.     MVI    B,10
  1135. EJECT2:    CALL    PBYT        ;PRINT 10 NULLS
  1136.     DCR    B
  1137.     JNZ    EJECT2
  1138.     MVI    A,00
  1139.     STA    LINES        ;SET LINE COUNT
  1140.     RET
  1141.  
  1142. ;********************************;
  1143. ;
  1144. ;      ISSUE CR, LF & TEST PAGE
  1145. ;
  1146. ;********************************;
  1147. CRLF:    MVI    E,0DH
  1148.     CALL    PBYT
  1149.     MVI    E,0AH
  1150.     CALL    PBYT
  1151.     LDA    LINES
  1152.     INR    A
  1153.     STA    LINES        ;INCREMENT LINE COUNT
  1154.     MVI    A,LPAGE        ;get number of lines
  1155.     ORA    A        ;is it zero?
  1156.     LDA    LINES
  1157.     RZ            ;YES, RETURN
  1158.     CPI    LPAGE        ;TEST LINE COUNT
  1159.     CZ    EJECT        ;IF EQ TO LPAGE THEN NEW PAGE
  1160.     RET
  1161.  
  1162.  
  1163. ;********************************;
  1164. ;
  1165. ;       CHARACTER PARSING TABLE
  1166. ;
  1167. ;********************************;
  1168. CTAB1:    DB    0DH
  1169.     DW    LCR
  1170.     DB    0AH
  1171.     DW    LLF
  1172.     DB    ''''
  1173.     DW    LQUOT
  1174.     DB    ';'
  1175.     DW    LSEMI
  1176.     DB    ' '
  1177.     DW    LSPC
  1178.     DB    09H
  1179.     DW    LTAB
  1180.     DB    '$'
  1181.     DW    LDOL
  1182.     DB    '('
  1183.     DW    LDEL
  1184.     DB    ')'
  1185.     DW    LDEL
  1186.     DB    '+'
  1187.     DW    LDEL
  1188.     DB    '-'
  1189.     DW    LDEL
  1190.     DB    '*'
  1191.     DW    LSEMI
  1192.     DB    '/'
  1193.     DW    LDEL
  1194.     DB    ','
  1195.     DW    LDEL
  1196.     DB    ':'
  1197.     DW    LDEL
  1198.     DB    EOF
  1199.     DW    DONE
  1200.     DB    0FFH
  1201.     DW    0000H
  1202. EOF    EQU    1AH        ;EOF CODE
  1203.  
  1204. ;********************************;
  1205. ;
  1206. ;     RESERVED WORD TABLE
  1207. ;
  1208. ;********************************;
  1209. RTAB:    DB    'A    '
  1210.     DB    'ACI  '
  1211.     DB    'ADC  '
  1212.     DB    'ADD  '
  1213.     DB    'ADI  '
  1214.     DB    'ANA  '
  1215.     DB    'AND  '
  1216.     DB    'ANI  '
  1217.     DB    'B    '
  1218.     DB    'C    '
  1219.     DB    'CALL '
  1220.     DB    'CC   '
  1221.     DB    'CM   '
  1222.     DB    'CMA  '
  1223.     DB    'CMC  '
  1224.     DB    'CMP  '
  1225.     DB    'CNC  '
  1226.     DB    'CNZ  '
  1227.     DB    'CP   '
  1228.     DB    'CPE  '
  1229.     DB    'CPI  '
  1230.     DB    'CPO  '
  1231.     DB    'CZ   '
  1232.     DB    'D    '
  1233.     DB    'DAA  '
  1234.     DB    'DAD  '
  1235.     DB    'DB   '
  1236.     DB    'DCR  '
  1237.     DB    'DCX  '
  1238.     DB    'DI   '
  1239.     DB    'DS   '
  1240.     DB    'DW   '
  1241.     DB    'E    '
  1242.     DB    'EI   '
  1243.     DB    'ELSE '
  1244.     DB    'END  '
  1245.     DB    'ENDIF'
  1246.     DB    'ENDM '
  1247.     DB    'EQU  '
  1248.     DB    'H    '
  1249.     DB    'HLT  '
  1250.     DB    'IF   '
  1251.     DB    'IN   '
  1252.     DB    'INR  '
  1253.     DB    'INX  '
  1254.     DB    'JC   '
  1255.     DB    'JM   '
  1256.     DB    'JMP  '
  1257.     DB    'JNC  '
  1258.     DB    'JNZ  '
  1259.     DB    'JP   '
  1260.     DB    'JPE  '
  1261.     DB    'JPO  '
  1262.     DB    'JZ   '
  1263.     DB    'L    '
  1264.     DB    'LDA  '
  1265.     DB    'LDAX '
  1266.     DB    'LHLD '
  1267.     DB    'LXI  '
  1268.     DB    'M    '
  1269.     DB    'MACRO'
  1270.     DB    'MOD  '
  1271.     DB    'MOV  '
  1272.     DB    'MVI  '
  1273.     DB    'NOP  '
  1274.     DB    'NOT  '
  1275.     DB    'OR   '
  1276.     DB    'ORA  '
  1277.     DB    'ORG  '
  1278.     DB    'ORI  '
  1279.     DB    'OUT  '
  1280.     DB    'PAGE '
  1281.     DB    'PCHL '
  1282.     DB    'POP  '
  1283.     DB    'PSW  '
  1284.     DB    'PUSH '
  1285.     DB    'RAL  '
  1286.     DB    'RAR  '
  1287.     DB    'RC   '
  1288.     DB    'RET  '
  1289.     DB    'RLC  '
  1290.     DB    'RM   '
  1291.     DB    'RNC  '
  1292.     DB    'RNZ  '
  1293.     DB    'RP   '
  1294.     DB    'RPE  '
  1295.     DB    'RPO  '
  1296.     DB    'RRC  '
  1297.     DB    'RST  '
  1298.     DB    'RZ   '
  1299.     DB    'SBB  '
  1300.     DB    'SBI  '
  1301.     DB    'SET  '
  1302.     DB    'SHL  '
  1303.     DB    'SHLD '
  1304.     DB    'SHR  '
  1305.     DB    'SP   '
  1306.     DB    'SPHL '
  1307.     DB    'STA  '
  1308.     DB    'STAX '
  1309.     DB    'STC  '
  1310.     DB    'SUB  '
  1311.     DB    'SUI  '
  1312.     DB    'TITLE'
  1313.     DB    'XCHG '
  1314.     DB    'XOR  '
  1315.     DB    'XRA  '
  1316.     DB    'XRI  '
  1317.     DB    'XTHL '
  1318.     DB    0FFH        ;END OF RESERVED WORD TABLE
  1319. RSIZ    EQU    05        ;SIZE OF TABLE ENTRY
  1320.  
  1321. ;********************************;
  1322. ;
  1323. ;       MISCELLANEOUS DATA
  1324. ;
  1325. ;********************************;
  1326.  
  1327. MSG1:    DB    'DISK CROSS REFERENCE FILE EXISTS - ERASE IT(Y/N)?','$'
  1328. EMSG0:    DB    '++ERROR++ INPUT FILE DOES NOT EXIST', 0DH, 0AH, '$'
  1329. EMSG1:    DB    'SYMBOL TABLE ERROR',0DH,0AH,'$'
  1330. EMSG2:    DB    'FAILED TO DELETE EXISTING CROSS REFERENCE FILE',0DH,0AH,'$'
  1331. EMSG3:    DB    'FAILED TO CREATE CROSS REFERENCE FILE',0DH,0AH,'$'
  1332. EMSG4:    DB    'DISK WRITE FAILED - OUT OF SPACE?',0DH,0AH,'$'
  1333. EMSG5:    DB    'CLOSE FAILED ON DISK CROSS REFERENCE FILE',0DH,0AH,'$'
  1334. EMSG6:    DB    '++ERROR++ NOT ENOUGH MEMORY FOR SYMBOL TABLE',0DH,0AH,'$'
  1335. EMSG7:    DB    '++ERROR++ SYMBOL TABLE OVERFLOW',0DH,0AH,'$'
  1336. LOGO:    DB    0Dh,0Ah,'CPM ASSEMBLER CROSS REFERENCE LIST Ver 1.41',0Dh,0Ah,'$'
  1337. DONEMSG: DB    'CROSS REFERENCE LIST IS DONE',0DH,0AH,'$'
  1338. NOSYMS:    DB    'NO SYMBOLS IN THIS PROGRAM'
  1339. CONCRLF    DB    0DH,0AH,'$'
  1340. SSIZ    EQU    SYMSIZ+3    ;SYMBOL TABLE ENTRY SIZE
  1341. SYMBT:    DS    2        ;SYMBOL TABLE BOTTOM ADDRESS
  1342. SYMTP:    DS    2        ;SYMBOL TABLE TOP ADDRESS
  1343. REFBT:    DS    2        ;REFERENCE TABLE BOTTOM ADDRESS
  1344. REFTP:    DS    2        ;REFERENCE TABLE TOP ADDRESS
  1345. SYM:    DS    2        ;CURRENT SYMBOL TABLE ADDRESS
  1346. REFSZ    EQU    2+(NREFS*2)    ;NUMBER OF BYTES IN REF BLOCK
  1347. REF:    DS    2        ;CURRENT REFERENCE TABLE ADDRESS
  1348. FROM:    DS    2        ;MOVE POINTER
  1349. TO:    DS    2        ;TO POINTER
  1350. LIMIT:    DS    2        ;LIMIT POINTER
  1351. COL:    DS    1
  1352. CHAR:    DS    1
  1353. LCNT:    DS    2        ;LINE COUNTER
  1354. LPNT:    DS    2
  1355. DEC:    DS    5
  1356.     DB    0DH
  1357. PBUF:    DS    132
  1358. SYMCT:    DS    1
  1359. SYMPT:    DS    2
  1360. SBUF:    DS    SYMSIZ        ;SYMBOL BUFFER
  1361. NLINS:    DB    0        ;BUFFERS TO PRINT ON LINE
  1362. LINES:    DB    0        ;PRINT LINE COUNT
  1363.  
  1364. ;********************************;
  1365. ;
  1366. ;       OPERATING SYSTEM EQUATES
  1367. ;
  1368. ;********************************;
  1369.  
  1370. BOOT    EQU    0000H    ;REBOOT ENTRY POINT
  1371. CPM    EQU    0005H    ;CPM ENTRY POINT
  1372.  
  1373. MEMSZ    EQU    0006H    ;END OF MEMORY POINTER
  1374. TFCB    EQU    005CH    ;TRANS. FCB
  1375.  
  1376. CONIN    EQU    01    ;CONSOLE INPUT FUNCTION CODE
  1377. PSTRING    EQU    09    ;PRINT STRING FUNCTION CODE
  1378. OPEN    EQU    15    ;OPEN FUNCTION CODE
  1379. CLOSE    EQU    16    ;CLOSE FILE FUNCTION CODE
  1380. DELETE    EQU    19    ;DELETE FILE FUNCTION CODE
  1381. READ    EQU    20    ;READ DISK FUNCTION CODE
  1382. WRITE    EQU    21    ;WRITE DISK FUNCTION CODE
  1383. MAKE    EQU    22    ;MAKE FILE FUNCTION CODE
  1384. SETDMA    EQU    26    ;SET DMA FUNCTION CODE
  1385.  
  1386.  
  1387.  
  1388. ;********************************;
  1389. ;           F O P E N            ;
  1390. ;  ROUTINE TO OPEN A DISK FILE   ;
  1391. ;                 ;
  1392. ;  INPUT:     DE=A(FCB)         ;
  1393. ;********************************;
  1394.  
  1395. FOPEN:    MVI    C,OPEN    ;OPEN CODE
  1396.     CALL    CPM    ;ISSUE OPEN
  1397.     CPI    0FFH    ;ERROR?
  1398.     RNZ        ;NO ERROR
  1399.     LXI    D,EMSG0
  1400.     JMP    FERR1
  1401.  
  1402. ;********************************;
  1403. ;                 ;
  1404. ; ROUTINE TO CLOSE OUTPUT DISK     ;
  1405. ;    CROSS REFERENCE FILE     ;
  1406. ;  INPUT:    DE=ADDR(FCB)     ;
  1407. ;        HL=ADDR(BUFFER)     ;
  1408. ;********************************;
  1409.  
  1410. DCLOSE:    PUSH    D        ;save fcb address
  1411.     PUSH    H        ;save buffer address
  1412.     LHLD    DSKCNT        ;put number of char left...
  1413.     XCHG            ;...in buffer into D,E
  1414.     LHLD    DCHAR        ;point to next char in output buf
  1415.     MVI    A,1AH        ;put a control Z in accum
  1416.  
  1417. DCLSE2:    MOV    M,A        ;fill...
  1418.     INX    H        ;...rest of...
  1419.     DCR    E        ;...buffer...
  1420.     JNZ    DCLSE2        ;...with...
  1421.     DCR    D        ;...control Z's.
  1422.     JNZ    DCLSE2
  1423.     POP    H        ;point to...
  1424.  
  1425. DCLSE4:    XCHG            ;...output buffer
  1426.     LXI    H,128        ;put 128 into H,L
  1427.     DAD    D        ;add 128 to disk buf addr for next DMA
  1428.     SHLD    BUFADR        ;save it for next DMA after this one
  1429.     MVI    C,SETDMA    ;...disk buffer for...
  1430.     CALL    CPM        ;...last disk write
  1431.     POP    D        ;do last...
  1432.     PUSH    D        ;....(D,E contains OFCB)...
  1433.     MVI    C,WRITE        ;...disk...
  1434.     CALL    CPM        ;...write
  1435. ;Check to see if last record has been written.  Do this by comparing
  1436. ;address of next available char to address of buffer for next disk write.
  1437. ;If address of next available char is equal or greater, close file.
  1438.     LHLD    DCHAR        ;put high order address
  1439.     XCHG            ;...of last char+1...
  1440.     MOV    A,D        ;...into ACCUM
  1441.     LHLD    BUFADR        ;get addr of next disk buffer
  1442.     CMP    H        ;compare to last char+1 in buffer
  1443.     JC    DCLSE5        ;if next addr is greater, close file
  1444.     JNZ    DCLSE4        ;if not equal, continue
  1445.     MOV    A,E        ;put low order address of last char+1
  1446.     CMP    L        ;into accum and test
  1447.     JNC    DCLSE4        ;if not less, do another write
  1448.  
  1449. DCLSE5:    POP    D        ;close the...(D,E contains OFCB)
  1450.     MVI    C,CLOSE        ;...output disk
  1451.     CALL    CPM        ;...cross ref file
  1452.     CPI    0FFH        ;close successfull?
  1453.     RNZ            ;yes, return
  1454.     LXI    D,EMSG5        ;no, display error msg...
  1455.     JMP    FERR1        ;... and quit
  1456.  
  1457. ;********************************;
  1458. ;            G E T B T           ;
  1459. ;   ROUTINE TO READ A BYTE       ;
  1460. ;                                ;
  1461. ;  OUTPUTS:     A=BYTE           ;
  1462. ;                 ;
  1463. ; 1. is current byte pointer at  ;
  1464. ;    end of buffer?         ;
  1465. ;    -yes, Read disk records     ;
  1466. ;     into buffer.         ;
  1467. ; 2. move character from buffer     ;
  1468. ;    to ACCUM.         ;
  1469. ; 3. add 1 to character pointer     ;
  1470. ;    and save pointer.     ;
  1471. ; 4. return to caller         ;
  1472. ;                 ;
  1473. ;********************************;
  1474.  
  1475. GETBT:    LXI    H,TBUF+(INSECT*128);end of input buf addr
  1476.     XCHG        ;BUFFER END ADDR. IN DE
  1477.     LHLD    INPTR    ;CURRENT POINTER IN HL
  1478.     CALL    CPHL    ;TEST FOR END OF BUFFER
  1479.     CZ    GETREC    ;YES, READ DISK RECORDS
  1480.     MOV    A,M    ;GET BYTE
  1481.     INX    H    ;BUMP POINTER
  1482.     SHLD    INPTR    ;SAVE POINTER
  1483.     ORA    A    ;CLEAR CARRY
  1484.     RET        ;RETURN CARRY RESET
  1485.  
  1486. ;***********************************************************
  1487. ;            GETREC
  1488. ;Read the number of input records specified by INSECT.  The
  1489. ;buffer starts at TBUF.  Before each DMA, the buffer address
  1490. ;is incremented by 128 and saved in IDADDR.  This address
  1491. ;will be used for the DMA after the current sector is read.
  1492. ;The logic is:
  1493. ;        1. get current buffer address
  1494. ;        2. add 128 to it and save it
  1495. ;        3. issue DMA for current buffer address
  1496. ;        4. read the disk record,
  1497. ;            -if end of file goto step 7.
  1498. ;        5. decrement number of sectors to read
  1499. ;        6. if not number of sectors not zero
  1500. ;            -repeat above
  1501. ;        7. reset character pointer to first buffer
  1502. ;        8. return to caller.
  1503. ;***********************************************************
  1504.  
  1505. GETREC:    MVI    B,INSECT;number of sectors to read
  1506.     LXI    H,TBUF    ;get address of disk input buffer
  1507.     SHLD    IDADDR    ;initialize current buffer address
  1508.  
  1509. GETRC2:    LHLD    IDADDR    ;get addr of input buffer
  1510.     XCHG        ;put it in D,E
  1511.     LXI    H,128    ;add 128 to input buf
  1512.     DAD    D    ;...addr for read after next
  1513.     SHLD    IDADDR    ;save it read after next
  1514.     PUSH    B    ;save sector count
  1515.     PUSH    D    ;save current buf ptr in case EOF occurrs
  1516.     MVI    C,SETDMA;POINT TO INPUT BUFFER...
  1517.     CALL    CPM
  1518.     MVI    C,READ    ;READ CODE
  1519.     LXI    D,TFCB    ;FCB ADDRESS
  1520.     CALL    CPM    ;ISSUE READ
  1521.     POP    D    ;restore current buf pointer
  1522.     POP    B    ;restore sector count
  1523.     CPI    00    ;ERROR?
  1524.     JNZ    GETRC4    ;YES
  1525.     DCR    B    ;read all of the sectors?
  1526.     JNZ    GETRC2    ;no, continue reading
  1527.  
  1528. GETRC3:    LXI    H,TBUF    ;RESET BUFFER POINTER
  1529.     SHLD    INPTR
  1530.     RET        ;RETURN TO CALLER
  1531.  
  1532. GETRC4:    XCHG        ;POINT TO FIRST CHAR PAST BUF
  1533.     MVI    M,26H    ;PUT TWO...
  1534.     INX    H    ;...CONTROL Z's
  1535.     MVI    M,26H    ;...AFTER LAST REC IN FILE
  1536.     JMP    GETRC3    ;GO RESET BUFFER POINTER
  1537.  
  1538. ;********************************;
  1539. ;   CONVERTS LOWER TO UPPER CASE ;
  1540. ;    INPUT: A=BYTE(upper/lower;
  1541. ;    OUTPUTS: A=BYTE UPPER     ;
  1542. ;********************************;
  1543.  
  1544. lwrupr:    cpi    'A'+20h    ;is it upper case?
  1545.     cmc        ;complement carry
  1546.     rnc        ;yes, return with carry reset
  1547.     Cpi    'Z'+21h    ;over lower case 'Z'?
  1548.     rnc        ;no, return no carry
  1549.     sui    20h    ;convert to upper case
  1550.     ret
  1551.  
  1552. ;********************************;
  1553. ;   MISCELLANEOUS SUBROUTINES    ;
  1554. ;********************************;
  1555.  
  1556.  
  1557. ;********************************;
  1558. ;             C P H L            ;
  1559. ;  ROUTINE TO COMPARE HL VS DE   ;
  1560. ;    OUTPUT: HL=DE, ZERO=ON     ;
  1561. ;        HL<>DE, ZERO=OFF ;
  1562. ;********************************;
  1563.  
  1564. CPHL:    MOV    A,H
  1565.     CMP    D
  1566.     RNZ
  1567.     MOV    A,L
  1568.     CMP    E
  1569.     RET
  1570.  
  1571. ;********************************;
  1572. ;             D A T A            ;
  1573. ;********************************;
  1574.  
  1575. OFCB:    DB    0    ;disk output fcb, default drive
  1576.     DS    8    ;file name
  1577.     DB    'XRF'    ;file type
  1578.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  1579.  
  1580. DCHAR:    DW    DISKBUF    ;pointer for disk buffer
  1581.  
  1582. BUFADR:    DS    2    ;pointer to disk output buffer for DMA
  1583.  
  1584. IDADDR:    DS    2    ;POINTER TO DISK INPUT BUFFER FOR DMA
  1585.  
  1586. DSKCNT:    DW    OUTSECT*128    ;number of char left in disk buffer
  1587.  
  1588. INPTR:    DW    TBUF+(INSECT*128);POINTER TO CHAR IN INPUT BUFFER
  1589.  
  1590. DISKBUF    DS    OUTSECT*128    ;output disk buffer
  1591.  
  1592. TBUF:    DS    INSECT*128    ;DISK INPUT BUFFER
  1593.  
  1594. EOFCHR:    DB    26H,26H    ;control Z's in case last block is
  1595.             ;filled with data
  1596.  
  1597. CONSOLE    DB    0    ;console output switch
  1598.  
  1599. DISKOUT    DB    0    ;disk output switch
  1600.  
  1601. FTPRN:    DB    1    ;prn file type
  1602.  
  1603. TEMP:    DS    2    ;TEMP SAVE WORD
  1604.  
  1605.     DS    64    ;stack contains 32 words
  1606. STACK    EQU    $
  1607.  
  1608. ;***********************************************
  1609. ;
  1610. ;        SYMBOL TABLE AREA
  1611. ;
  1612. ;    THE SYMBOL TABLE MUST BE THE
  1613. ;    LAST BYTE BEFORE THE HELP MESSAGE
  1614. ;
  1615. ;***********************************************
  1616.  
  1617.     ORG    ($ AND 0FFF0H) + 10H    ;FORCE 16 BYTE BOUNDARY
  1618. SYMT:    DB    0FFH
  1619.  
  1620. HELP:    DB    0DH,0AH,'This program can be used to' 
  1621.     DB    ' create a cross reference listing',0DH,0AH
  1622.     DB    'of CPM assembler programs.'
  1623.     DB    '  The input can be either the assembler',0DH,0AH
  1624.     DB    'language source code(FN.ASM) or the assembly listing(FN.PRN).',0DH,0AH
  1625.     DB    'The output can be printed on the CPM list device, displayed on',0DH,0AH
  1626.     DB    'the console, or written to disk(file type will be XRF).  It is',0DH,0AH
  1627.     DB    'invoked by keying:',0DH,0AH,0AH
  1628.     DB    09H,'XREF FN.ASM      (OUTPUT ON LIST DEVICE)',0DH,0AH
  1629.     DB    09H,'XREF FN.PRN CON  (OUTPUT ON THE CONSOLE)',0DH,0AH
  1630.     DB    09H,'XREF FN.ASM D    (OUTPUT ON DISK-DEFAULT DRIVE)',0DH,0AH
  1631.     DB    09H,'XREF FN.PRN B:D  (OUTPUT ON DISK-DRIVE SPECIFIED)',0DH,0AH,'$'
  1632.  
  1633.     END
  1634.