home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / xref241.lbr / XREF241.AQM / XREF241.ASM
Assembly Source File  |  1985-02-09  |  31KB  |  1,352 lines

  1. ;    TITLE    XREF.ASM  VER 2.41    01/30/83
  2. ;
  3. ;    for assembly with LASM.COM
  4. ;
  5. ;    cross reference program  
  6. ;    for asm and mac files
  7. ;
  8. ;        version 2.41
  9. ;
  10. ;       jeff kravitz 
  11. ;
  12. ;    modified by     john mahr
  13. ;            ray malitzke z80, m80
  14. ;
  15. LPAGE    EQU    00        ;num lines per page if peject is true
  16. NREFS    EQU    03        ;number of references per ref tbl entry
  17. LREFS    EQU    21        ;references per output line
  18. SYMSIZ    EQU    08        ;number of symbol char
  19. OUTSECT    EQU    01        ;number of disk sectors written from buffer
  20. INSECT    EQU    08        ;number of disk sectors read into buffer
  21. ;
  22. ;          main loop
  23. ;
  24. ;    ASEG
  25.     ORG    100H        ;origin address
  26. XREF:    LXI    SP,STACK    ;set stack pointer
  27.     CALL    SETUP        ;initialize
  28. MAIN:    CALL    GETBT        ;get a byte from source file
  29.     CALL    SAVBT        ;save byte in print buffer
  30. MAIN2:    CALL    CKNUM        ;test for numeric
  31.     JNC    LNUM        ;yes, found a number, process
  32.     CALL    CKALP        ;test for alphabetic
  33.     JNC    LALPH        ;yes, process
  34.     LXI    H,CTAB1        ;point to character table
  35.     CALL    LOOK        ;look up char in char table
  36.     JC    LIGN        ;not found, ignore
  37.     PCHL            ;execute routine
  38. ;
  39. ;        done
  40. ;
  41. ;      final symbol table print
  42. ;
  43. DONE:    CALL    EJECT        ;issue page eject
  44.     LHLD    SYMBT        ;get symbol table bottom
  45.     MVI    A,0FFH        ;check to see if there were...
  46.     CMP    M        ;...any symbols in the program
  47.     JZ    DLP4        ;no, don't print symbol table
  48.     SHLD    SYM        ;set symbol pointer
  49.     LHLD    SYMTP        ;get symbol table top
  50.     MVI    M,0FFH        ;end off symbol table
  51. DLP1:    LHLD    SYM        ;get symbol table pointer
  52.     CALL    PSYM        ;print symbol
  53.     LHLD    SYM
  54.     LXI    D,SYMSIZ+1    ;offset to ref link
  55.     DAD    D
  56.     MOV    E,M
  57.     INX    H
  58.     MOV    D,M        ;get ref block addr
  59.     XCHG            ;into hl
  60.     SHLD    REF
  61.     CALL    PREFS        ;print references
  62.     LHLD    SYM        ;get symbol table pointer
  63.     LXI    D,SSIZ        ;size of sym table entry
  64.     DAD    D
  65.     SHLD    SYM
  66.     MOV    A,M        ;get byte
  67.     CPI    0FFH        ;end of table?
  68.     JNZ    DLP1        ;loop
  69.  
  70. DLP2:    CALL    EJECT        ;page eject
  71.     LDA    DISKOUT        ;get disk output switch
  72.     ORA    A        ;disk output being used?
  73.     JZ    DLP3        ;no, issue end msg & return to cpm
  74.     LXI    H,DISKBUF    ;get output disk buffer
  75.     LXI    D,OFCB        ;and out fcb
  76.     CALL    DCLOSE        ;and close output disk file
  77.  
  78. DLP3:    LXI    D,TFCB        ;close the...
  79.     MVI    C,CLOSE        ;...input...
  80.     CALL    CPM        ;...file.
  81.     LXI    D,DONEMSG    ;tell operator...
  82.     MVI    C,PSTRING    ;...that pgm is...
  83.     CALL    CPM        ;...done
  84.     JMP    BOOT        ;and return to cp/m
  85.  
  86. DLP4:    LXI    H,NOSYMS    ;get no symbol message
  87.     MVI    B,28        ;number of char in msg
  88. DLP5:    MOV    E,M        ;print the...
  89.     CALL    PBYT        ;...message
  90.     INX    H
  91.     DCR    B
  92.     JNZ    DLP5
  93.     JMP    DLP2        ;go close files
  94. ;
  95. ;     symbol print routine
  96. ;
  97. PSYM:    MVI    B,SYMSIZ    ;symbol size
  98. PSYM2:    MOV    E,M        ;get byte
  99.     CALL    PBYT        ;print byte
  100.     INX    H
  101.     DCR    B
  102.     JNZ    PSYM2
  103.     MVI    E,' '
  104.     CALL    PBYT        ;print 2 spaces
  105.     CALL    PBYT
  106.     RET
  107. ;
  108. ;     reference print routine
  109. ;
  110. PREFS:    MVI    A,LREFS/NREFS    ;number of blocks to print on one line
  111.     STA    NLINS        ;to nlins
  112. PREF0:    LHLD    REF        ;get ref block addr
  113.     INX    H
  114.     INX    H        ;bump to first ref number
  115.     SHLD    TEMP        ;save ref num addr
  116.     MVI    A,(REFSZ-2)/2    ;number of ref slots
  117.     STA    SYMCT        ;save in symct
  118. PREF:    LHLD    TEMP        ;get ref slot addr
  119.     MOV    E,M
  120.     INX    H
  121.     MOV    D,M        ;get ref
  122.     LXI    H,0000        ;zero?
  123.     CALL    CPHL
  124.     JZ    CRLF        ;yes, done
  125.     XCHG            ;get num in hl
  126.     CALL    DECOT        ;convert
  127.     LXI    H,DEC        ;point to dec string
  128.     MVI    M,' '        ;blank leading zero
  129.     MVI    B,5        ;number of digits + 1 in ref num
  130. PREF2:    MOV    E,M
  131.     CALL    PBYT        ;print byte
  132.     INX    H
  133.     DCR    B
  134.     JNZ    PREF2        ;print reference number
  135.     LHLD    TEMP        ;get ref slot addr
  136.     INX    H
  137.     INX    H        ;bump to next slot
  138.     SHLD    TEMP
  139.     LDA    SYMCT        ;get count
  140.     DCR    A        ;decrement
  141.     STA    SYMCT
  142.     JNZ    PREF
  143.     LHLD    REF        ;get ref block address
  144.     MOV    E,M
  145.     INX    H
  146.     MOV    D,M        ;get link to next block
  147.     LXI    H,0000
  148.     CALL    CPHL        ;any more blocks?
  149.     JZ    CRLF        ;no, exit
  150.     XCHG            ;yes, set next block pointer in ref
  151.     SHLD    REF
  152.     LDA    NLINS
  153.     DCR    A        ;decrement lines count
  154.     STA    NLINS
  155.     JNZ    PREF0        ;and print more on same line
  156.     CALL    CRLF        ;print cr,lf
  157.     MVI    B,SYMSIZ+2    ;indent continuation line...
  158. PREF3:    MVI    E,' '        ;...with spaces
  159.     CALL    PBYT        ;print spaces
  160.     DCR    B
  161.     JNZ    PREF3        ;print 6 spaces
  162.     JMP    PREFS
  163. ;
  164. ;   character parsing routines
  165. ;
  166. LALPH:    LXI    H,SBUF        ;point to symbol buffer
  167.     MVI    C,SYMSIZ
  168.     MVI    A,' '        ;fill symbol...
  169. LALX:    MOV    M,A        ;...with...
  170.     INX    H        ;...blanks
  171.     DCR    C
  172.     JNZ    LALX        ;clear symbol buffer
  173.     LXI    H,SBUF
  174.     SHLD    SYMPT
  175.     MVI    A,00
  176.     STA    SYMCT        ;reset symbol pointer+count
  177.     LDA    CHAR        ;get character again
  178.     CALL    GTSYM        ;collect identifier
  179. LALC:    CALL    GETBT        ;get a byte from source file
  180.     CALL    SAVBT        ;save byte in print buffer
  181.     CALL    CKNUM        ;test for number
  182.     JNC    LAL3        ;yes, continue
  183.     CALL    CKALP        ;test for alphabetic
  184.     JNC    LAL3        ;yes, continue
  185.     CALL    CRES        ;test for reserved word
  186.     JC    LAL1        ;no, continue
  187. LAL0:    LDA    CHAR        ;get character that ended id
  188.     JMP    MAIN2        ;continue scan
  189. LAL1:    CALL    FIND        ;see if defined
  190.     JC    LAL2        ;no, continue
  191.     CALL    ADDRF        ;yes, add reference
  192.     JMP    LAL0        ;done
  193. LAL2:    CALL    ENSYM        ;enter symbol definition
  194.     CALL    ADDRF        ;add reference
  195.     JMP    LAL0        ;continue
  196. LAL3:    CALL    GTSYM        ;collect identifier
  197.     JMP    LALC        ;continue
  198. ;
  199. LNUM:    CALL    GETBT        ;get byte
  200.     CALL    SAVBT        ;save byte in printer buffer
  201.     CALL    CKNUM        ;test for numeric
  202.     JNC    LNUM        ;yes, continue
  203.     CALL    CKALP        ;test for alphabetic
  204.     JNC    LNUM        ;yes, continue
  205.     JMP    MAIN2        ;continue with main scan
  206. ;
  207. LQUOT:    CALL    GETBT        ;get a byte
  208.     CALL    SAVBT        ;save byte in printer buffer
  209.     CPI    ''''        ;see if string quote
  210.     JNZ    LQUOT        ;no, keep looping
  211.     CALL    GETBT        ;get next byte
  212.     CALL    SAVBT        ;save byte
  213.     CPI    ''''        ;test for doubles
  214.     JZ    LQUOT        ;yes, start scan again
  215.     JMP    MAIN2        ;no, continue in main scan
  216. ;
  217. LSEMI:    CALL    GETBT        ;get a byte
  218.     CALL    SAVBT        ;save byte
  219.     CPI    0DH        ;wait for cr
  220.     JNZ    LSEMI        ;continue
  221.     JMP    MAIN2        ;enter main loop
  222. ;
  223. LCR:    CALL    PLINE        ;print line
  224.     LHLD    LCNT        ;get line number
  225.     INX    H        ;bump line number
  226.     SHLD    LCNT        ;store
  227.     JMP    MAIN
  228. ;
  229. LLF:    PUSH    PSW        ;save char
  230.     LDA    FTPRN        ;is it file...
  231.     ORA    A        ;...type prn?
  232.     JZ    LLF2        ;yes, skip 1rst 16 char
  233.     POP    PSW        ;restore char
  234.     JMP    MAIN
  235. ;
  236. LLF2:    POP    PSW        ;restore character
  237.     MVI    B,16        ;# of char to skip over
  238. ;
  239. LLF3:    CALL    GETBT        ;get next byte
  240.     CALL    SAVBT        ;put in print buf
  241.     CPI    0DH        ;carriage return?
  242.     JZ    LCR        ;yes, get next line
  243.     DCR    B        ;skipped all char?
  244.     JNZ    LLF3        ;no, continue skipping
  245.     JMP    MAIN        ;continue
  246. ;
  247. LIGN:    JMP    MAIN        ;re-enter main loop
  248. ;
  249. LSPC    EQU    LIGN
  250. LTAB    EQU    LIGN
  251. LDOL    EQU    LIGN
  252. LDEL    EQU    LIGN
  253. ;
  254. ;
  255. ;          subroutines
  256. ;
  257. ;    setup or initialization
  258. ;
  259.  
  260. SETUP:    LXI    D,LOGO        ;get program logo msg
  261.     MVI    C,PSTRING    ;bdos print string
  262.     CALL    CPM        ;print logo
  263.     LDA    TFCB+1        ;get first char of file name
  264.     CPI    '?'        ;help function?
  265.     JNZ    SETUP1        ;no, go check input file type
  266.     LXI    D,HELP        ;display help message
  267.     JMP    FERR1
  268.  
  269. SETUP1:    LDA    TFCB+9        ;get first char of file type
  270.     CPI    'P'        ;is it type prn?
  271.     JNZ    SETUP2        ;no, don't set switch
  272.     LDA    TFCB+10        ;get 2nd char of file type
  273.     CPI    'R'
  274.     JNZ    SETUP2
  275.     LDA    TFCB+11        ;get 3rd char of file type
  276.     CPI    'N'
  277.     JNZ    SETUP2
  278.     XRA    A
  279.     STA    FTPRN        ;turn on prn file type
  280. ;
  281. SETUP2:    LDA    TFCB+17        ;get 1rst char of 2nd fcb
  282.     CPI    'C'        ;output to console?
  283.     JNZ    SETUP3        ;no, don't turn on switch
  284.     LDA    TFCB+18        ;get 2nd char of 2nd fcb
  285.     CPI    'O'        ;output to console?
  286.     JNZ    SETUP3        ;no, don't turn on switch
  287.     MVI    A,0FFH        ;turn on...
  288.     STA    CONSOLE        ;...console output
  289.     JMP    SETUP6        ;go open input file
  290. SETUP3:    LDA    TFCB+17        ;get 1rst char of 2nd fcb
  291.     CPI    'D'        ;output to be written to disk?
  292.     JNZ    SETUP6        ;no, go open input file.
  293.     STA    DISKOUT        ;turn on disk output switch
  294.     LDA    TFCB+16        ;get output file drive number
  295.     STA    OFCB        ;move to output fcb
  296.     LXI    D,TFCB        ;point to fcb
  297.     CALL    FOPEN        ;open disk input file
  298.     LXI    D,TFCB+1    ;point to input file name
  299.     MVI    B,8        ;length of file name
  300.     LXI    H,OFCB+1    ;point to output fcb file name
  301.     CALL    MOVE        ;move input file name to output fcb
  302.     LXI    D,OFCB        ;does output file...
  303.     MVI    C,OPEN        ;...already...
  304.     CALL    CPM        ;...exist?
  305.     CPI    0FFH        ;open succeed?
  306.     JZ    SETUP4        ;no, file does not exist
  307. ;
  308.     LXI    D,OFCB        ;close...
  309.     MVI    C,CLOSE        ;...the open...
  310.     CALL    CPM        ;...file.
  311.     LXI    D,MSG1        ;ask operator...
  312.     MVI    C,PSTRING    ;...if old file...
  313.     CALL    CPM        ;...is to be...
  314.     MVI    C,CONIN        ;...deleted
  315.     CALL    CPM
  316.     ANI    05FH        ;make upper case
  317.     CPI    'Y'        ;operator say yes?
  318.     JNZ    BOOT        ;no, terminate
  319. ;
  320.     LXI    D,CONCRLF    ;write carriage return...
  321.     MVI    C,PSTRING    ;...line feed to console
  322.     CALL    CPM
  323.     LXI    D,OFCB        ;point to fcb to delete file
  324.     MVI    C,DELETE    ;delete the...
  325.     CALL    CPM        ;...file
  326.     CPI    0FFH        ;delete succeed?
  327.     LXI    D,EMSG2        ;get err msg in case of failure
  328.     JZ    FERR1        ;failure, print msg & quit
  329. ;
  330. SETUP4:    LXI    D,OFCB        ;point to output fcb
  331.     MVI    C,MAKE        ;create new...
  332.     CALL    CPM        ;...cross reference file.
  333.     CPI    0FFH        ;create succeed?
  334.     LXI    D,EMSG3        ;get err msg in case of failure
  335.     JZ    FERR1        ;create failed, print msg & quit
  336.     LXI    H,DISKBUF    ;get addr of disk buffer
  337.     SHLD    DCHAR        ;init disk char pointer
  338. ;
  339. SETUP6:    LXI    D,TFCB        ;point to fcb
  340.     CALL    FOPEN        ;open fcb
  341.     LXI    H,PBUF
  342.     SHLD    LPNT        ;set print pointer
  343.     LXI    H,00001        ;set line counter...
  344.     SHLD    LCNT        ;...to one.
  345.     LXI    H,SYMT        ;get address of symbol table
  346.     SHLD    SYM
  347.     SHLD    SYMBT
  348.     SHLD    SYMTP        ;set symbol table pointers
  349.     LHLD    MEMSZ        ;get available memory address
  350.     DCX    H
  351.     SHLD    REF
  352.     SHLD    REFBT
  353.     SHLD    REFTP        ;set reference table pointers
  354.     RET
  355. ;
  356. ;    check for reserved word
  357. ;
  358. CRES:    LXI    H,RTAB        ;point to reserved word table
  359.     SHLD    TEMP        ;save in temp word
  360. CRES1:    LHLD    TEMP        ;get table pointer
  361.     LXI    D,SBUF        ;point to symbol
  362.     MVI    B,5        ;symbol size
  363. CRES2:    LDAX    D        ;get symbol byte
  364.     CMP    M        ;compare against table entry
  365.     RC            ;less, not in table
  366.     JNZ    CRES3        ;greater, get next table entry
  367.     INX    D        ;bump pointers
  368.     INX    H
  369.     DCR    B        ;decrement byte count
  370.     JNZ    CRES2        ;keep testing
  371.     JMP    CRES4        ;found
  372. CRES3:    LHLD    TEMP        ;get table pointer
  373.     LXI    D,RSIZ        ;size of entry
  374.     DAD    D        ;bump pointer
  375.     SHLD    TEMP        ;store new pointer
  376.     MOV    A,M        ;get table byte
  377.     CPI    0FFH        ;end of table?
  378.     JNZ    CRES1        ;no, loop
  379.     STC            ;set carry (not in table)
  380.     RET
  381. CRES4:    ORA    A        ;reset carry
  382.     RET
  383. ;
  384. ;     find symbol in table
  385. ;
  386. FIND:    LHLD    SYMBT        ;get begin of sym table
  387.     SHLD    SYM        ;set temp pointer
  388. FIND1:    LHLD    SYM        ;get temp pointer
  389.     LXI    D,SBUF        ;point to current symbol
  390.     MVI    B,SYMSIZ    ;symbol size
  391. FIND2:    LDAX    D        ;get byte from sbuf
  392.     CMP    M        ;compare to sym table byte
  393.     RC            ;greater, not in table
  394.     JNZ    FIND3        ;less, get next table entry
  395.     INX    D        ;bump pointer
  396.     INX    H        ;bump pointer
  397.     DCR    B        ;decrement byte count
  398.     JNZ    FIND2        ;loop
  399.     RET            ;true zero, found
  400. FIND3:    LHLD    SYM        ;get current pointer
  401.     LXI    D,SSIZ        ;symbol table entry size
  402.     DAD    D        ;bump pointer
  403.     XCHG            ;into de
  404.     LHLD    SYMTP        ;get top of symbol table
  405.     CALL    CPHL        ;test for end of table
  406.     JZ    FIND4        ;yes, done
  407.     JC    FERR        ;table overflow, error
  408.     XCHG            ;current pointer into hl
  409.     SHLD    SYM        ;set current pointer
  410.     JMP    FIND1        ;loop
  411. FIND4:    STC            ;set carry for not found
  412.     LHLD    SYMTP        ;get current top
  413.     SHLD    SYM        ;set current pointer
  414.     RET
  415. ;
  416. FERR:    LXI    D,EMSG1        ;symbol table err msg
  417. FERR1:    MVI    C,PSTRING    ;write console
  418.     CALL    CPM        ;issue error message
  419.     JMP    BOOT        ;exit
  420. ;
  421. FERR2:    LXI    D,EMSG6        ;no room for symbol table
  422.     JMP    FERR1
  423. ;
  424. ;   add reference to ref table
  425. ;
  426. ADDRF:    LHLD    SYM        ;get symbol pointer
  427.     LXI    D,SYMSIZ+1    ;offset past symbol&flags
  428.     DAD    D
  429.     MOV    E,M
  430.     INX    H
  431.     MOV    D,M        ;get reference pointer
  432.     LXI    H,0000
  433.     CALL    CPHL        ;test for zero ref ptr
  434.     JZ    BLDRF        ;yes, build reference entry
  435. LINK1:    XCHG            ;ref ptr in hl
  436.     MOV    E,M        ;get ref link
  437.     INX    H
  438.     MOV    D,M        ;into de
  439.     DCX    H        ;reposition hl
  440.     PUSH    H        ;save ref ptr
  441.     LXI    H,0000
  442.     CALL    CPHL        ;if link is zero
  443.     POP    H
  444.     JNZ    LINK1        ;non zero, get next link
  445.     SHLD    REF        ;save ref pointer
  446.     INX    H
  447.     INX    H        ;skip to first ref number
  448.     MVI    B,(REFSZ-2)/2    ;number of ref numbers/entry
  449. LINK3:    MOV    E,M        ;get ref number
  450.     INX    H
  451.     MOV    D,M
  452.     DCX    H        ;reposition
  453.     PUSH    H        ;save ref num addr
  454.     LXI    H,0000
  455.     CALL    CPHL        ;see if ref num is zero
  456.     POP    H
  457.     JZ    ENREF        ;yes, enter reference
  458.     INX    H
  459.     INX    H        ;skip to next ref num
  460.     DCR    B        ;decrement count
  461.     JNZ    LINK3        ;try again at next slot
  462.     CALL    ADBLK        ;add new ref block
  463.     LHLD    REF        ;get ref pointer
  464.     INX    H
  465.     INX    H        ;skip to first ref slot
  466. ENREF:    PUSH    H        ;save ref slot addr
  467.     LHLD    LCNT        ;get line number
  468.     XCHG            ;into de
  469.     POP    H        ;get ref slot addr
  470.     MOV    M,E
  471.     INX    H
  472.     MOV    M,D        ;store line ref
  473.     RET            ;done
  474. ;
  475. ;     build ref table block
  476. ;
  477. BLDRF:    LHLD    SYM        ;get symbol pointer
  478.     LXI    D,SYMSIZ+1    ;offset to ref pointer
  479.     DAD    D
  480.     SHLD    REF        ;set temp ref pointer to here
  481.     CALL    ADBLK        ;add block
  482.     LHLD    REF        ;get real ref pointer
  483.     INX    H
  484.     INX    H        ;position to first ref slot
  485.     JMP    ENREF        ;add reference
  486. ADBLK:    LHLD    REFBT        ;get ref bottom
  487.     LXI    D,REFSZ        ;subtract ref size
  488.     MOV    A,L
  489.     SUB    E
  490.     MOV    L,A
  491.     MOV    A,H
  492.     SBB    D
  493.     MOV    H,A
  494.     SHLD    TEMP        ;save new ref bottom
  495.     XCHG            ;into de also
  496.     LHLD    SYMTP        ;get symbol top
  497.     CALL    CPHL        ;check for bump
  498.     JZ    FERR2        ;yes, no room
  499.     JNC    FERR2        ;no room
  500.     LHLD    TEMP        ;get ref bottom
  501.     XCHG            ;into de
  502.     LHLD    REF        ;get ref pointer
  503.     MOV    M,E        ;set link
  504.     INX    H
  505.     MOV    M,D        ;to new ref block
  506.     LHLD    TEMP        ;get new ref block addr
  507.     SHLD    REF        ;store in ref
  508.     MVI    B,REFSZ        ;size of ref block
  509.     MVI    A,00
  510. ADB2:    MOV    M,A        ;zero the ref block
  511.     INX    H
  512.     DCR    B
  513.     JNZ    ADB2
  514.     LHLD    TEMP        ;get new ref bottom
  515.     SHLD    REFBT        ;set refbt
  516.     RET
  517. ;
  518. ;     enter symbol in sym table
  519. ;
  520. ENSYM:    LHLD    SYM        ;get symbol pointer
  521.     XCHG            ;into de
  522.     LHLD    SYMTP        ;get symbol table top
  523.     CALL    CPHL        ;check for end of table
  524.     JZ    NWSYM        ;yes, add symbol at end
  525.     LXI    D,SSIZ        ;symbol table entry size
  526.     DAD    D        ;calculate new end of table
  527.     XCHG            ;into de
  528.     LHLD    REFBT        ;reference table bottom
  529.     CALL    CPHL        ;test for table overflow
  530.     LXI    D,EMSG7        ;addr of err msg in of overflow
  531.     JZ    FERR1        ;full, error
  532.     JC    FERR1        ;yes, error
  533.     LHLD    SYMTP        ;get table top
  534.     LXI    D,SSIZ-1    ;bump to end of entry
  535.     DAD    D
  536.     SHLD    TO        ;store in to address
  537.     LXI    D,SSIZ
  538.     MOV    A,L
  539.     SUB    E
  540.     MOV    L,A
  541.     MOV    A,H
  542.     SBB    D
  543.     MOV    H,A        ;subtract size of one entry
  544.     SHLD    FROM        ;store as from address
  545.     LHLD    SYM        ;get current pointer
  546.     SHLD    LIMIT        ;store as limit address
  547.     CALL    MVUP        ;move table up in memory
  548. NWSYM:    LHLD    SYM        ;get current pointer
  549.     LXI    D,SBUF        ;point to symbol
  550.     MVI    B,SYMSIZ    ;size of symbol
  551.     CALL    MOVE        ;copy symbol to table
  552.     MVI    A,0
  553.     MOV    M,A
  554.     INX    H
  555.     MOV    M,A
  556.     INX    H
  557.     MOV    M,A        ;set pointers to 0000
  558.     LHLD    SYMTP        ;get symbol table top
  559.     LXI    D,SSIZ        ;get symbol entry size
  560.     DAD    D        ;bump
  561.     SHLD    SYMTP        ;store ew top
  562.     RET
  563. ;
  564. ;    move symbol table up
  565. ;
  566. MVUP:    LHLD    TO        ;get to pointer
  567.     MOV    B,H
  568.     MOV    C,L        ;into bc
  569.     LHLD    FROM        ;get from pointer
  570.     XCHG            ;into de
  571.     LHLD    LIMIT        ;get limit address
  572. MVUP2:    LDAX    D        ;get from byte
  573.     STAX    B        ;store at to address
  574.     CALL    CPHL        ;compare from to limit
  575.     RZ            ;exit if done
  576.     DCX    B        ;decrement to
  577.     DCX    D        ;decrment from
  578.     JMP    MVUP2        ;loop
  579. ;
  580. ;  general purpose move routine
  581. ;
  582. MOVE:    LDAX    D        ;get byte
  583.     MOV    M,A        ;store byte
  584.     INX    D
  585.     INX    H        ;bump pointers
  586.     DCR    B        ;decrement count
  587.     JNZ    MOVE        ;loop
  588.     RET
  589. ;
  590. ;    binary to decimal conversion
  591. ;
  592. DECOT:    LXI    D,DEC
  593.     XCHG
  594.     LXI    B,10000
  595.     CALL    DIG
  596.     LXI    B,1000
  597.     CALL    DIG
  598.     LXI    B,100
  599.     CALL    DIG
  600.     LXI    B,10
  601.     CALL    DIG
  602.     LXI    B,1
  603.     CALL    DIG
  604.     RET
  605. ;
  606. DIG:    MVI    M,'0'
  607. DI0:    MOV    A,E
  608.     SUB    C
  609.     MOV    E,A
  610.     MOV    A,D
  611.     SBB    B
  612.     MOV    D,A
  613.     JM    DI2
  614.     INR    M
  615.     JMP    DI0
  616. DI2:    MOV    A,E
  617.     ADD    C
  618.     MOV    E,A
  619.     MOV    A,D
  620.     ADC    B
  621.     MOV    D,A
  622.     INX    H
  623.     RET
  624. ;
  625. ;    test for alphabetic char.
  626. ;
  627. CKALP:    CPI    '$'        ;treat '$' like a char
  628.     RZ
  629.     CPI    'A'        ;ascii 'A'
  630.     RC            ;no, exit
  631.     CPI    'Z'+1
  632.     CMC
  633.     RET
  634. ;
  635. ;       test for numeric char
  636. ;
  637. CKNUM:    CPI    '0'
  638.     RC
  639.     CPI    '9'+1
  640.     CMC
  641.     RET
  642. ;
  643. ;  look up char in parse table
  644. ;
  645. LOOK:    LXI    D,0003        ;table entry size
  646.     MOV    B,A        ;argument byte in b
  647. LOOK2:    MOV    A,M        ;get table byte
  648.     CPI    0FFH        ;end of table?
  649.     JZ    LOOKN        ;yes, not found
  650.     CMP    B        ;compare
  651.     JZ    LOOKY        ;found
  652.     DAD    D        ;bump pointer
  653.     JMP    LOOK2        ;loop
  654. LOOKN:    STC            ;carry = not found
  655.     RET
  656. ;
  657. LOOKY:    INX    H        ;skip to table byte
  658.     MOV    E,M
  659.     INX    H
  660.     MOV    D,M        ;table entry in de
  661.     XCHG            ;into hl
  662.     RET
  663. ;
  664. ;    save byte in line buffer
  665. ;
  666. SAVBT:    LHLD    LPNT        ;get line pointer
  667.     MOV    M,A        ;save byte
  668.     INX    H        ;bump pointer
  669.     SHLD    LPNT        ;save pointer
  670.     CALL    LWRUPR        ;convert lower to upper case
  671.     STA    CHAR        ;save char in char
  672.     RET
  673. ;
  674. ;  print source line with number
  675. ;
  676. PLINE:    LHLD    LCNT        ;get line number
  677.     CALL    DECOT        ;convert to decimal
  678.     LXI    H,DEC        ;point to dec string
  679. PL2:    MOV    E,M        ;get string byte
  680.     MOV    A,E
  681.     CPI    0DH        ;done?
  682.     JZ    PL3        ;yes
  683.     CALL    PBYT        ;print byte
  684.     INX    H        ;bump pointer
  685.     JMP    PL2
  686. PL3:    MVI    E,':'
  687.     CALL    PBYT        ;print ':'
  688.     MVI    E,' '
  689.     CALL    PBYT        ;print ' '
  690.     CALL    PBYT        ;print space
  691.     LXI    H,PBUF        ;point to print buffer
  692.     MVI    A,00
  693.     STA    COL        ;set column count
  694. PL41:    MOV    E,M        ;get byte
  695.     MOV    A,E
  696.     CPI    0DH        ;done?
  697.     JZ    PL5
  698.     CPI    0AH        ;lf?
  699.     JZ    PL4A        ;yes, ignore
  700.     CPI    09H        ;tab?
  701.     JNZ    PL42        ;no, continue
  702.     PUSH    H        ;save hl
  703. PL43:    MVI    E,' '
  704.     CALL    PBYT        ;print space
  705.     LXI    H,COL
  706.     INR    M
  707.     MOV    A,M
  708.     ANI    07H        ;modulo 8
  709.     JNZ    PL43
  710.     POP    H
  711.     JMP    PL4A
  712. PL42:    LDA    COL
  713.     INR    A
  714.     STA    COL
  715.     CALL    PBYT        ;print byte
  716. PL4A:    INX    H
  717.     JMP    PL41
  718. PL5:    CALL    CRLF        ;print cr,lf
  719.     LXI    H,PBUF
  720.     SHLD    LPNT        ;reset line pointer
  721.     RET
  722. ;
  723. ;      collect symbol in sym buf
  724. ;
  725. GTSYM:    MOV    B,A        ;save char
  726.     LDA    SYMCT        ;get symbol count
  727.     CPI    SYMSIZ        ;max?
  728.     RNC            ;yes, done 
  729.     INR    A
  730.     STA    SYMCT
  731.     LHLD    SYMPT
  732.     MOV    M,B
  733.     INX    H        ;bump symbol pointer
  734.     SHLD    SYMPT
  735.     RET
  736. ;
  737. ;       printer interfaces
  738. ;
  739. ;
  740. ;       print a single byte
  741. ;
  742. PBYT:    PUSH    B
  743.     PUSH    D
  744.     PUSH    H
  745.     PUSH    PSW
  746.     LDA    DISKOUT        ;disk output...
  747.     ORA    A        ;...in effect?
  748.     JNZ    DBYT        ;yes, go write to disk
  749.     MVI    C,05
  750.     LDA    CONSOLE        ;get console out switch
  751.     ORA    A        ;console output?
  752.     JZ    PBYT2        ;no, print output
  753.     MVI    C,2        ;console output
  754. ;
  755. PBYT2:    CALL    CPM
  756. ;
  757. PBYT3:    MVI    C,11        ;check console status
  758.     CALL    CPM
  759.     ORA    A        ;if zero, ok
  760.     JZ    PBYTX        ;exit
  761.     MVI    C,1
  762.     CALL    CPM        ;read console char
  763.     CPI    3
  764.     JZ    BOOT        ;abort if ^c, otherwise ignore
  765. PBYTX:    POP    PSW
  766.     POP    H
  767.     POP    D
  768.     POP    B
  769.     RET
  770. ;
  771. ;        dbyt
  772. ;
  773. ;    put output character
  774. ;    into disk buffer.
  775. ;        input=e(output char)
  776. ;
  777. ;
  778. DBYT:    MOV    A,E        ;save char to be put in buffer
  779.     LHLD    DSKCNT        ;get num of char left in buf
  780.     XCHG            ;put num in d,e
  781.     LHLD    DCHAR        ;point to next char in buf
  782.     MOV    M,A        ;put char in disk buf
  783.     DCR    E        ;at end of buf?
  784.     JNZ    DBYT1        ;no, don't write buffer
  785.     DCR    D        ;at end of buf?
  786.     JZ    PUTREC        ;yes, go write buffer
  787. ;
  788. DBYT1:    INX    H        ;point to next char in buf
  789.     SHLD    DCHAR        ;save next pos
  790.     XCHG            ;put num of char left in h,l
  791.     SHLD    DSKCNT        ;save num of remaining char
  792.     JMP    PBYT3        ;go check console status
  793. ;
  794. ;        putrec
  795. ;    write out disk buffer to disk
  796. ;
  797. PUTREC:    LXI    H,DISKBUF    ;address of disk buffer
  798.     SHLD    BUFADR        ;save it for later dma's
  799.     MVI    B,OUTSECT    ;number of disk sectors to write
  800. ;
  801. PUTRC2:    PUSH    B        ;save sector count
  802.     LHLD    BUFADR        ;get disk buffer address
  803.     XCHG            ;put it in d,e for dma
  804.     LXI    H,80H        ;put 128 h,l
  805.     DAD    D        ;add 128 to disk buf adr for next dma
  806.     SHLD    BUFADR        ;save it for next dma
  807.     MVI    C,SETDMA    ;point dma to...
  808.     CALL    CPM        ;...correct buffer
  809.     LXI    D,OFCB        ;get output disk fcb
  810.     MVI    C,WRITE        ;write sector...
  811.     CALL    CPM        ;...to disk
  812.     ORA    A        ;was write successfull?
  813.     POP    B        ;restore num of sectors left
  814.     LXI    D,EMSG4        ;get err msg in case write failed
  815.     JNZ    FERR1        ;disk write failed, display err msg, quit
  816.     DCR    B        ;written 16 sectors yet?
  817.     JNZ    PUTRC2        ;no, continue writing disk sectors
  818.     LXI    H,OUTSECT*128    ;put disk buffer size into h,l
  819.     SHLD    DSKCNT        ;set num of char left in buf to buffer size
  820.     LXI    H,DISKBUF    ;point to front...
  821.     SHLD    DCHAR        ;...of disk buffer
  822.     JMP    PBYT3        ;go check console status for ^c
  823. ;
  824. ;      issue page eject
  825. ;
  826. EJECT:    MVI    E,0CH        ;printer eject command
  827.     CALL    PBYT
  828.     MVI    E,00H
  829.     MVI    B,10
  830. EJECT2:    CALL    PBYT        ;print 10 nulls
  831.     DCR    B
  832.     JNZ    EJECT2
  833.     MVI    A,00
  834.     STA    LINES        ;set line count
  835.     RET
  836. ;
  837. ;      issue cr, lf & test page
  838. ;
  839. CRLF:    MVI    E,0DH
  840.     CALL    PBYT
  841.     MVI    E,0AH
  842.     CALL    PBYT
  843.     LDA    LINES
  844.     INR    A
  845.     STA    LINES        ;increment line count
  846.     MVI    A,LPAGE        ;get number of lines
  847.     ORA    A        ;is it zero?
  848.     LDA    LINES
  849.     RZ            ;yes, return
  850.     CPI    LPAGE        ;test line count
  851.     CZ    EJECT        ;if eq to lpage then new page
  852.     RET
  853. ;
  854. ;       character parsing table
  855. ;
  856. CTAB1:    DB    0DH
  857.     DW    LCR
  858.     DB    0AH
  859.     DW    LLF
  860.     DB    ''''
  861.     DW    LQUOT
  862.     DB    ';'
  863.     DW    LSEMI
  864.     DB    ' '
  865.     DW    LSPC
  866.     DB    09H
  867.     DW    LTAB
  868.     DB    '$'
  869.     DW    LDOL
  870.     DB    '('
  871.     DW    LDEL
  872.     DB    ')'
  873.     DW    LDEL
  874.     DB    '+'
  875.     DW    LDEL
  876.     DB    '-'
  877.     DW    LDEL
  878.     DB    '*'
  879.     DW    LSEMI
  880.     DB    '/'
  881.     DW    LDEL
  882.     DB    ','
  883.     DW    LDEL
  884.     DB    ':'
  885.     DW    LDEL
  886.     DB    EOF
  887.     DW    DONE
  888.     DB    0FFH
  889.     DW    0000H
  890. EOF    EQU    1AH        ;eof code
  891. ;
  892. ;     reserved word table
  893. ;
  894. RTAB:    DB    '8080 '
  895.     DB    'A    '
  896.     DB    'ACI  '
  897.     DB    'ADC  '
  898.     DB    'ADD  '
  899.     DB    'ADI  '
  900.     DB    'AF   '
  901.     DB    'ANA  '
  902.     DB    'AND  '
  903.     DB    'ANI  '
  904.     DB    'ASEG '
  905.     DB    'B    '
  906.     DB    'BC   '
  907.     DB    'BIT  '
  908.     DB    'C    '
  909.     DB    'CALL '
  910.     DB    'CC   '
  911.     DB    'CCF  '
  912.     DB    'CM   '
  913.     DB    'CMA  '
  914.     DB    'CMC  '
  915.     DB    'CMP  '
  916.     DB    'CNC  '
  917.     DB    'CNZ  '
  918.     DB    'COMME'
  919.     DB    'COMMO'
  920.     DB    'COND '
  921.     DB    'CP   '
  922.     DB    'CPD  '
  923.     DB    'CPDR '
  924.     DB    'CPE  '
  925.     DB    'CPI  '
  926.     DB    'CPL  '
  927.     DB    'CPO  '
  928.     DB    'CSEG '
  929.     DB    'CZ   '
  930.     DB    'D    '
  931.     DB    'DAA  '
  932.     DB    'DAD  '
  933.     DB    'DB   '
  934.     DB    'DC   '
  935.     DB    'DCR  '
  936.     DB    'DCX  '
  937.     DB    'DE   '
  938.     DB    'DEC  '
  939.     DB    'DEFB '
  940.     DB    'DEFL '
  941.     DB    'DEFM '
  942.     DB    'DEFW '
  943.     DB    'DI   '    
  944.     DB    'DJNZ '
  945.     DB    'DS   '    
  946.     DB    'DSEG '
  947.     DB    'DW   '
  948.     DB    'E    '
  949.     DB    'EI   '
  950.     DB    'ELSE '
  951.     DB    'END  '
  952.     DB    'ENDC '
  953.     DB    'ENDIF'
  954.     DB    'ENDM '
  955.     DB    'ENTRY'
  956.     DB    'EQ   '
  957.     DB    'EQU  '
  958.     DB    'EX   '
  959.     DB    'EXX  '
  960.     DB    'EXITM'
  961.     DB    'EXT  '    
  962.     DB    'EXTRN'
  963.     DB    'GE   '
  964.     DB    'GLOBA'
  965.     DB    'GT   '
  966.     DB    'H    '
  967.     DB    'HL   '
  968.     DB    'HIGH '
  969.     DB    'HALT '
  970.     DB    'IF   '
  971.     DB    'IFB  '    
  972.     DB    'IFDEF'
  973.     DB    'IFE  '
  974.     DB    'IFF  '
  975.     DB    'IFNB '
  976.     DB    'IFNDE'
  977.     DB    'IFT  '
  978.     DB    'IF1  '
  979.     DB    'IF2  '
  980.     DB    'IM   '
  981.     DB    'IN   '
  982.     DB    'INC  '
  983.     DB    'INCLU'
  984.     DB    'IND  '
  985.     DB    'INDR '
  986.     DB    'INIR '
  987.     DB    'INR  '
  988.     DB    'INX  '
  989.     DB    'IRP  '
  990.     DB    'IRPC '
  991.     DB    'IX   '    
  992.     DB    'IY   '
  993.     DB    'JC   '
  994.     DB    'JM   '
  995.     DB    'JMP  '
  996.     DB    'JNC  '
  997.     DB    'JNZ  '
  998.     DB    'JP   '
  999.     DB    'JPE  '
  1000.     DB    'JPO  '
  1001.     DB    'JR   '
  1002.     DB    'JZ   '
  1003.     DB    'L    '
  1004.     DB    'LALL '
  1005.     DB    'LD   '
  1006.     DB    'LDA  '
  1007.     DB    'LDAX '
  1008.     DB    'LDD  '    
  1009.     DB    'LDDR '
  1010.     DB    'LDI  '
  1011.     DB    'LDIR '    
  1012.     DB    'LE   '    
  1013.     DB    'LHLD '
  1014.     DB    'LIST '
  1015.     DB    'LOCAL'
  1016.     DB    'LOW  '
  1017.     DB    'LT   '
  1018.     DB    'LXI  '
  1019.     DB    'M    '
  1020.     DB    'MACRO'
  1021.     DB    'MOD  '
  1022.     DB    'MOV  '
  1023.     DB    'MVI  '
  1024.     DB    'NAME '
  1025.     DB    'NC   '
  1026.     DB    'NE   '
  1027.     DB    'NEG  '
  1028.     DB    'NOP  '
  1029.     DB    'NOT  '
  1030.     DB    'NUL  '
  1031.     DB    'NZ   '
  1032.     DB    'OR   '
  1033.     DB    'ORA  '
  1034.     DB    'ORG  '
  1035.     DB    'ORI  '
  1036.     DB    'OTDR '
  1037.     DB    'OTIR '
  1038.     DB    'OUT  '
  1039.     DB    'OUTI '
  1040.     DB    'OUTD '
  1041.     DB    'PAGE '
  1042.     DB    'PCHL '
  1043.     DB    'P    '
  1044.     DB    'PE   '
  1045.     DB    'PO   '
  1046.     DB    'POP  '
  1047.     DB    'PRINT'
  1048.     DB    'PSW  '
  1049.     DB    'PUBLI'
  1050.     DB    'PUSH '
  1051.     DB    'RADIX'
  1052.     DB    'RAL  '
  1053.     DB    'RAR  '
  1054.     DB    'RC   '
  1055.     DB    'REPT '
  1056.     DB    'RES  '
  1057.     DB    'RET  '
  1058.     DB    'RETI '
  1059.     DB    'RL   '
  1060.     DB    'RLA  '
  1061.     DB    'RLC  '
  1062.     DB    'RLCA '
  1063.     DB    'RLD  '
  1064.     DB    'RM   '
  1065.     DB    'RNC  '
  1066.     DB    'RNZ  '
  1067.     DB    'RP   '
  1068.     DB    'RPE  '
  1069.     DB    'RPO  '
  1070.     DB    'RR   '
  1071.     DB    'RRA  '
  1072.     DB    'RRC  '
  1073.     DB    'RRCA '
  1074.     DB    'RRD  '
  1075.     DB    'RST  '
  1076.     DB    'RZ   '
  1077.     DB    'SALL '
  1078.     DB    'SBB  '
  1079.     DB    'SBC  '
  1080.     DB    'SBI  '
  1081.     DB    'SCF  '
  1082.     DB    'SET  '
  1083.     DB    'SHL  '
  1084.     DB    'SHLD '
  1085.     DB    'SHR  '
  1086.     DB    'SLA  '
  1087.     DB    'SP   '
  1088.     DB    'SPHL '
  1089.     DB    'SRA  '
  1090.     DB    'SRL  '
  1091.     DB    'STA  '
  1092.     DB    'STAX '
  1093.     DB    'STC  '
  1094.     DB    'SUB  '
  1095.     DB    'SUBTT'
  1096.     DB    'SUI  '
  1097.     DB    'TITLE'
  1098.     DB    'XALL '
  1099.     DB    'XCHG '
  1100.     DB    'XLIST'
  1101.     DB    'XOR  '
  1102.     DB    'XRA  '
  1103.     DB    'XRI  '
  1104.     DB    'XTHL '
  1105.     DB    'Z    '
  1106.     DB    'Z80  '
  1107.     DB    0FFH        ;end of reserved word table
  1108. RSIZ    EQU    05        ;size of table entry
  1109. ;
  1110. ;       miscellaneous data
  1111. ;
  1112. MSG1:    DB    'DISK CROSS REFERENCE FILE EXISTS - ERASE IT(Y/N)?','$'
  1113. EMSG0:    DB    '++ERROR++ INPUT FILE DOES NOT EXIST', 0DH, 0AH, '$'
  1114. EMSG1:    DB    'SYMBOL TABLE ERROR',0DH,0AH,'$'
  1115. EMSG2:    DB    'FAILED TO DELETE EXISTING CROSS REFERENCE FILE',0DH,0AH,'$'
  1116. EMSG3:    DB    'FAILED TO CREATE CROSS REFERENCE FILE',0DH,0AH,'$'
  1117. EMSG4:    DB    'DISK WRITE FAILED - OUT OF SPACE?',0DH,0AH,'$'
  1118. EMSG5:    DB    'CLOSE FAILED ON DISK CROSS REFERENCE FILE',0DH,0AH,'$'
  1119. EMSG6:    DB    '++ERROR++ NOT ENOUGH MEMORY FOR SYMBOL TABLE',0DH,0AH,'$'
  1120. EMSG7:    DB    '++ERROR++ SYMBOL TABLE OVERFLOW',0DH,0AH,'$'
  1121. LOGO:    DB    0DH,0AH,'CPM ASSEMBLER CROSS REFERENCE LIST Ver 2.41',0DH,0AH,'$'
  1122. DONEMSG: DB    'CROSS REFERENCE LIST IS DONE',0DH,0AH,'$'
  1123. NOSYMS:    DB    'NO SYMBOLS IN THIS PROGRAM'
  1124. CONCRLF:DB    0DH,0AH,'$'
  1125. SSIZ    EQU    SYMSIZ+3    ;symbol table entry size
  1126. SYMBT:    DS    2        ;symbol table bottom address
  1127. SYMTP:    DS    2        ;symbol table top address
  1128. REFBT:    DS    2        ;reference table bottom address
  1129. REFTP:    DS    2        ;reference table top address
  1130. SYM:    DS    2        ;current symbol table address
  1131. REFSZ    EQU    2+(NREFS*2)    ;number of bytes in ref block
  1132. REF:    DS    2        ;current reference table address
  1133. FROM:    DS    2        ;move pointer
  1134. TO:    DS    2        ;to pointer
  1135. LIMIT:    DS    2        ;limit pointer
  1136. COL:    DS    1
  1137. CHAR:    DS    1
  1138. LCNT:    DS    2        ;line counter
  1139. LPNT:    DS    2
  1140. DEC:    DS    5
  1141.     DB    0DH
  1142. PBUF:    DS    132
  1143. SYMCT:    DS    1
  1144. SYMPT:    DS    2
  1145. SBUF:    DS    SYMSIZ        ;symbol buffer
  1146. NLINS:    DB    0        ;buffers to print on line
  1147. LINES:    DB    0        ;print line count
  1148. ;
  1149. ;       operating system equates
  1150. ;
  1151. BOOT    EQU    0000H    ;reboot entry point
  1152. CPM    EQU    0005H    ;cpm entry point
  1153. ;
  1154. MEMSZ    EQU    0006H    ;end of memory pointer
  1155. TFCB    EQU    005CH    ;trans. fcb
  1156. ;
  1157. CONIN    EQU    01    ;console input function code
  1158. PSTRING    EQU    09    ;print string function code
  1159. OPEN    EQU    15    ;open function code
  1160. CLOSE    EQU    16    ;close file function code
  1161. DELETE    EQU    19    ;delete file function code
  1162. READ    EQU    20    ;read disk function code
  1163. WRITE    EQU    21    ;write disk function code
  1164. MAKE    EQU    22    ;make file function code
  1165. SETDMA    EQU    26    ;set dma function code
  1166. ;
  1167. ;           f o p e n            ;
  1168. ;  routine to open a disk file   ;
  1169. ;                 ;
  1170. ;  input:     de=a(fcb)         ;
  1171. ;
  1172. FOPEN:    MVI    C,OPEN    ;open code
  1173.     CALL    CPM    ;issue open
  1174.     CPI    0FFH    ;error?
  1175.     RNZ        ;no error
  1176.     LXI    D,EMSG0
  1177.     JMP    FERR1
  1178. ;                 ;
  1179. ; routine to close output disk     ;
  1180. ;    cross reference file     ;
  1181. ;  input:    de=addr(fcb)     ;
  1182. ;        hl=addr(buffer)     ;
  1183. ;
  1184. DCLOSE:    PUSH    D        ;save fcb address
  1185.     PUSH    H        ;save buffer address
  1186.     LHLD    DSKCNT        ;put number of char left...
  1187.     XCHG            ;...in buffer into d,e
  1188.     LHLD    DCHAR        ;point to next char in output buf
  1189.     MVI    A,1AH        ;put a control z in accum
  1190. DCLSE2:    MOV    M,A        ;fill...
  1191.     INX    H        ;...rest of...
  1192.     DCR    E        ;...buffer...
  1193.     JNZ    DCLSE2        ;...with...
  1194.     DCR    D        ;...control z's.
  1195.     JNZ    DCLSE2
  1196.     POP    H        ;point to...
  1197. ;
  1198. DCLSE4:    XCHG            ;...output buffer
  1199.     LXI    H,128        ;put 128 into h,l
  1200.     DAD    D        ;add 128 to disk buf addr for next dma
  1201.     SHLD    BUFADR        ;save it for next dma after this one
  1202.     MVI    C,SETDMA    ;...disk buffer for...
  1203.     CALL    CPM        ;...last disk write
  1204.     POP    D        ;do last...
  1205.     PUSH    D        ;....(d,e contains ofcb)...
  1206.     MVI    C,WRITE        ;...disk...
  1207.     CALL    CPM        ;...write
  1208. ;
  1209. ;check to see if last record has been written.  do this by comparing
  1210. ;address of next available char to address of buffer for next disk write.
  1211. ;if address of next available char is equal or greater, close file.
  1212.     LHLD    DCHAR        ;put high order address
  1213.     XCHG            ;...of last char+1...
  1214.     MOV    A,D        ;...into accum
  1215.     LHLD    BUFADR        ;get addr of next disk buffer
  1216.     CMP    H        ;compare to last char+1 in buffer
  1217.     JC    DCLSE5        ;if next addr is greater, close file
  1218.     JNZ    DCLSE4        ;if not equal, continue
  1219.     MOV    A,E        ;put low order address of last char+1
  1220.     CMP    L        ;into accum and test
  1221.     JNC    DCLSE4        ;if not less, do another write
  1222. ;
  1223. DCLSE5:    POP    D        ;close the...(d,e contains ofcb)
  1224.     MVI    C,CLOSE        ;...output disk
  1225.     CALL    CPM        ;...cross ref file
  1226.     CPI    0FFH        ;close successfull?
  1227.     RNZ            ;yes, return
  1228.     LXI    D,EMSG5        ;no, display error msg...
  1229.     JMP    FERR1        ;... and quit
  1230. ;
  1231. ;            g e t b t
  1232. ;   routine to read a byte
  1233. ;
  1234. ;  outputs:     a=byte
  1235. ;
  1236. GETBT:    LXI    H,TBUF+(INSECT*128) ;end of input buf addr
  1237.     XCHG        ;buffer end addr. in de
  1238.     LHLD    INPTR    ;current pointer in hl
  1239.     CALL    CPHL    ;test for end of buffer
  1240.     CZ    GETREC    ;yes, read disk records
  1241.     MOV    A,M    ;get byte
  1242.     INX    H    ;bump pointer
  1243.     SHLD    INPTR    ;save pointer
  1244.     ORA    A    ;clear carry
  1245.     RET        ;return carry reset
  1246. ;
  1247. ;            getrec
  1248. ;
  1249. GETREC:    MVI    B,INSECT ;number of sectors to read
  1250.     LXI    H,TBUF    ;get address of disk input buffer
  1251.     SHLD    IDADDR    ;initialize current buffer address
  1252.  
  1253. GETRC2:    LHLD    IDADDR    ;get addr of input buffer
  1254.     XCHG        ;put it in d,e
  1255.     LXI    H,128    ;add 128 to input buf
  1256.     DAD    D    ;...addr for read after next
  1257.     SHLD    IDADDR    ;save it read after next
  1258.     PUSH    B    ;save sector count
  1259.     PUSH    D    ;save current buf ptr in case eof occurrs
  1260.     MVI    C,SETDMA ;point to input buffer...
  1261.     CALL    CPM
  1262.     MVI    C,READ    ;read code
  1263.     LXI    D,TFCB    ;fcb address
  1264.     CALL    CPM    ;issue read
  1265.     POP    D    ;restore current buf pointer
  1266.     POP    B    ;restore sector count
  1267.     CPI    00    ;error?
  1268.     JNZ    GETRC4    ;yes
  1269.     DCR    B    ;read all of the sectors?
  1270.     JNZ    GETRC2    ;no, continue reading
  1271.  
  1272. GETRC3:    LXI    H,TBUF    ;reset buffer pointer
  1273.     SHLD    INPTR
  1274.     RET        ;return to caller
  1275.  
  1276. GETRC4:    XCHG        ;point to first char past buf
  1277.     MVI    M,26H    ;put two...
  1278.     INX    H    ;...control z's
  1279.     MVI    M,26H    ;...after last rec in file
  1280.     JMP    GETRC3    ;go reset buffer pointer
  1281. ;
  1282. ;   converts lower to upper case ;
  1283. ;    input: a=byte(upper/lower;
  1284. ;    outputs: a=byte upper     ;
  1285. ;
  1286. LWRUPR: CPI    'A'+20H    ;is it upper case?
  1287.     CMC        ;complement carry
  1288.     RNC        ;yes, return with carry reset
  1289.     CPI    'Z'+21H    ;over lower case 'Z'?
  1290.     RNC        ;no, return no carry
  1291.     SUI    20H    ;convert to upper case
  1292.     RET
  1293. ;
  1294. ;   miscellaneous subroutines    ;
  1295. ;
  1296. ;             c p h l            ;
  1297. ;  routine to compare hl vs de   ;
  1298. ;    output: hl=de, zero=on     ;
  1299. ;        hl<>de, zero=off ;
  1300. ;
  1301. CPHL:    MOV    A,H
  1302.     CMP    D
  1303.     RNZ
  1304.     MOV    A,L
  1305.     CMP    E
  1306.     RET
  1307. ;
  1308. ;             d a t a 
  1309. ;
  1310. OFCB:    DB    0    ;disk output fcb, default drive
  1311.     DS    8    ;file name
  1312.     DB    'XRF'    ;file type
  1313.     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
  1314. DCHAR:    DW    DISKBUF    ;pointer for disk buffer
  1315. BUFADR:    DS    2    ;pointer to disk output buffer for dma
  1316. IDADDR:    DS    2    ;pointer to disk input buffer for dma
  1317. DSKCNT:    DW    OUTSECT*128    ;number of char left in disk buffer
  1318. INPTR:    DW    TBUF+(INSECT*128);pointer to char in input buffer
  1319. DISKBUF:DS    OUTSECT*128    ;output disk buffer
  1320. TBUF:    DS    INSECT*128    ;disk input buffer
  1321. EOFCHR:    DB    26H,26H    ;control z's in case last block is
  1322.             ;filled with data
  1323. CONSOLE:DB    0    ;console output switch
  1324. DISKOUT:DB    0    ;disk output switch
  1325. FTPRN:    DB    1    ;prn file type
  1326. TEMP:    DS    2    ;temp save word
  1327.     DS    64    ;stack contains 32 words
  1328. STACK    EQU    $
  1329. ;
  1330. ;        symbol table area
  1331. ;
  1332. ;    the symbol table must be the
  1333. ;    last byte before the help message
  1334. ;
  1335.     ORG    $    ;10h + (0fff0h and $)  ;force 16 byte boundary
  1336. SYMT:    DB    0FFH
  1337. ;
  1338. HELP:    DB    0DH,0AH,'This program can be used to' 
  1339.     DB    ' create a cross reference listing',0DH,0AH
  1340.     DB    'of CPM assembler programs.'
  1341.     DB    '  The input can be either the assembler',0DH,0AH
  1342.     DB    'language source code(FN.ASM) or the assembly listing(FN.PRN).',0DH,0AH
  1343.     DB    'The output can be printed on the CPM list device, displayed on',0DH,0AH
  1344.     DB    'the console, or written to disk(file type will be XRF).  It is',0DH,0AH
  1345.     DB    'invoked by keying:',0DH,0AH,0AH
  1346.     DB    09H,'XREF FN.ASM      (OUTPUT ON LIST DEVICE)',0DH,0AH
  1347.     DB    09H,'XREF FN.PRN CON  (OUTPUT ON THE CONSOLE)',0DH,0AH
  1348.     DB    09H,'XREF FN.ASM D    (OUTPUT ON DISK-DEFAULT DRIVE)',0DH,0AH
  1349.     DB    09H,'XREF FN.PRN B:D  (OUTPUT ON DISK-DRIVE SPECIFIED)',0DH,0AH,'$'
  1350. ;
  1351.     END    XREF
  1352.