home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
beehive
/
zcat
/
xref27.lbr
/
XREF27.AZM
/
XREF27.ASM
Wrap
Assembly Source File
|
1991-01-31
|
45KB
|
1,695 lines
; XREF27.ASM Cross-reference program for .ASM or .PRN files 11/09/85
;
;
; This program generates a cross-reference list for all labels in an
; .ASM, .MAC or .PRN file. Thus it works with either an assembly level
; source code file or an assembled print file. No other cross-reference
; program is known to have this sort of versatility and ease of use. It
; will number the lines and generate a cross-reference listing at the
; end of the program. If a numbered listing is not requested, it makes
; a cross-reference listing without the source code - this is often used
; to find what label names have been already used - or which labels were
; actually unnecessary as they were not used at all. The output can be
; shown to the CRT, sent directly to the printer, or to a disk file. If
; a disk file is used, it is given the same name as the original file,
; with an .EXR extent.
;
;-----------------------------------------------------------------------
; current revision
;
; 11/09/85 Fixed an intermittent bug that was causing the program to
; v27 miss seeing the EOF character and keep right on going until
; it bombed by filling the disk. This occured on some longer
; .PRN files when adding line numbers. Took awhile to find,
; as only occured occasionally. Likely been around since the
; program was written. - Irv Hoff
;
;-----------------------------------------------------------------------
;
; It is invoked by entering:
;
; XREF FILEBNME.ASM (output to printer)
; XREF FILENAME.PRN CRT (output to CRT)
; XREF FILENAME.ASM D (output to disk - default drive)
; XREF FILENAME.PRN B:D (output to disk - drive B: in this case)
;
; To get the help guide type:
;
; XREF ? <ret> or XREF <ret>
;
;-----------------------------------------------------------------------
; Number of lines per output page set by equ LPAGE. Set this equate to
; zero if you don't want any form feeds added in the cross-reference
; listing - it will still put one at the beginning and end.
;
; NREFS sets the number of label references per table entry. This
; value should be set to the average number of references that a label
; will have in the program. It is used to build the label reference
; table entries. Each entry will be equal to (NREFS*2)+2. If it is
; made unnecessarily large, then the label reference table will be very
; large with a lot of unused slots. Example: a program with 300 labels
; will require a reference table that is at least 12600 bytes if
; NREFS=20, whereas the same program will require a reference table that
; is at least 3600 bytes if NREFS=5. Each label that exceeds NREFS re-
; ferences will require ((Total references/NREFS) rounded up) reference
; table entries. Recommended values: 3-5.
;
; LREFS sets the Number of labels references to be printed per output
; line. It should be a multiple of NREFS. If it is not, then the first
; number that is less than LREFS and is a multiple of NREFS will be
; printed on the line. Example: if NREFS is 5 and LREFS is 13, then
; only 10 entries will be printed per line. The total number of refer-
; ences that will fit on one line without overflow is equal to the size
; of the line minus (LABSIZ+2) divided by 6. Example: if the line size
; is 72 characters and LABSIZ equals 10, then total number of references
; per line can be INT((72-(10+2))/6) or INT(60/6) or 10.
;
; LABSIZ sets the Label size. This is the label size that the program
; will use in the cross reference listing. It should be large enough to
; make each label unique in cross-reference listing. If a label is
; larger than the value for LABSIZ, then the label will be truncated in
; the output i.e., LARGE$LABEL would be LARGE$LABE if LABSIZ was set to
; 10. Recommended value is 8.
;
; BUFSIZ is the number of disk records that will be read when the disk
; input buffer is empty. It is used to calculate the size of the input
; buffer and output buffers. Input buffer size = BUFSIZ * 128. Recom-
; mended value is from 8 to 32. 16 works well. This represents a 2k
; buffer. Remember there are separate buffers of this size for input
; and output, doubling the total memory used.
;
;
; NOTE: If INSECT is made too large, there will not be enough memory
; left to build the cross-reference table for a large program. Largest
; tested values so far is 916 on a 64k system. The file successfully
; cross-referenced was MDM740.PRN. - JRM
;
;-----------------------------------------------------------------------
;
; DONE
; ----
; DONE gets control when a control Z(1AH) is found
; in the input data stream. This routine:
;
; 1) issues a page eject
; 2) prints the cross reference table
; 3) issues a page eject
; 4) if disk output, writes out the remaining
; sectors in the disk output buffer and
; then closes the disk output file
; 5) closes the disk input file
; 6) displays end of program message
;
;
; SETUP OR INITIALIZATION
; -----------------------
; 1) displays program logo and version
; 2) checks for input file type PRN
; -if file type PRN, sets PRN switch
; 3) if operator specified FN.FT CON, then sets console
; output switch on. Goes to step 5
; 4) else check for disk output option
; -if not disk output, default to printer output
; -go to step 5
; -else check to see if cross reference file exists
; -if it exists, ask operater if it is to be erased
; -if no erase, terminate program
; -else erase cross reference file
; -then create new cross reference disk file
; -initialize output character pointer to disk buffer
; 5) open input disk file
; 6) initialize printer buffer, address pointers for label table
; and reference table, set line counter to 1
; 7) return to caller
;
; DBYT
; ----
; Put output character into disk buffer
;
; Input = E (output character)
;
; 1) move character to buffer
; 2) if at end of buffer, go
; write out disk buffer
; 3) else add 1 to disk buffer
; pointer
; 4) subtract 1 from number of
; positions left in buffer
; 5) go check if operator pressed ^C
;
;
; PUTREC
; ------
; Write out disk buffer to disk
;
; 1) initialize start of disk buffer address and number
; of sectors to write out
; 2) get current disk sector buffer address
; 3) add 128 to it and save for DMA of sector after
; current sector
; 4) do DMA for current sector buffer address
; 5) write current disk sector
; 6) if not last sector repeat steps 2 thru 5
; 7) set number of characters positions left in buffer
; to size of buffer
; 8) set disk output buffer pointer to front of buffer
; 9) go check to see if operator pressed control C
;
;
; GETBT
; -----
; Routine to read a byte
;
; Outputs: A=byte
;
; 1) is current byte pointer at
; end of buffer?
; -yes, Read disk records
; into buffer
; 2) move character from buffer
; to ACCUM
; 3) add 1 to character pointer
; and save pointer
; 4) return to caller
;
;
; GETREC
; ------
; Read the number of input records specified by BUFSIZ. The buffer
; starts at TBUF. Before each DMA, the buffer address is incremented by
; 128 and saved in IDADDR. This address will be used for the DMA after
; the current sector is read. The logic is:
;
; 1) get current buffer address
; 2) add 128 to it and save it
; 3) issue DMA for current buffer address
; 4) read the disk record,
; -if end of file goto step 7
; 5) decrement number of sectors to read
; 6) if not number of sectors not zero
; -repeat above
; 7) reset character pointer to first buffer
; 8) return to caller
;
;-----------------------------------------------------------------------
; prior updates
; 09/09/85 Rewrote the display routine so it has all reference numbers
; v26 lined up uniformly, with a leading asterisk on the number
; representing the line where the label is defined. Other
; changes. - Irv Hoff
;
; 01/13/85 Modified help message and introduced XRF-only option, most
; v25 editors can easily find a line with a number. Added markers
; " >>" for label-definition. Shortened line number display
; to be consistent with CREF output. Moved code to conserve
; space. Moved comments from M80 source which are no longer
; needed as LASM is there and does the job.
; - B. Eiben
;
; 01/30/83 Added operation (and pseudo) codes for the Z80 and M80 as-
; v24 semblers. While M80 CREF80 are superior they are limited by
; the size of the CRF files since instead of TAB space fill is
; used (an 80K MAC file expands to a 240K CRF file). This
; program will handle at least 1200 labels in 48K RAM. Even
; without flagging the defining statement, this program is
; quite useful. - RMG
;
; 03/15/82 This program would lock up if there was a comment line that
; v23 started with an asterisk '*' instead of a semicolon. The
; program then processed the whole line as a valid line of as-
; sembly-level code. This usually resulted in the cross re-
; ference program locking up if there were a lot of lines that
; started with an asterisk. The program now treats an aster-
; isk the same as a semicolon. This was done by changing the
; table CTAB1 so that the program branches to LSEMI when it
; finds an asterisk. Also fixed bug that occurred when the
; last record of a file was completely filled with data and
; thus had no control Z's (EOF characters) in it. This was
; done by always placing two control Z's after the last record
; was read. Finally fixed a bug that showed up only when a
; program had no symbols or labels in it. Added a check for
; an empty label table before attempting to print the label
; symbol table. - JRM
;
; 03/06/82 Changed the code so the size of output disk buffer can be
; v22 specified at assembly time. The size is set by OUTSECT
; which equals the number of disk sectors to be written when
; the buffer is full. Implemented the same feature for disk
; input. INSECT sets the number of disk records to be read
; into the input buffer. On file type PRN the was a bug.
; Whenever the first label on a line was preceded by a char-
; acter, the line was not listed in the cross-reference list-
; ing. This was caused by skipping over the first 16 char-
; acters in the line on a CR (carriage return) instead of on a
; LF (line feed). This bug has been fixed. Added help func-
; tion. This is invoked by entering XFER ?
; - JRM
;
; 03/03/82 Added a 2k buffer for disk output writes. This was done to
; v21 speed up the execution of program when disk output was spec-
; ified. Fixed bug when page size was specified. CP/M assem-
; bler was not doing the conditional IF assembly correctly.
; Changed the code to test if page size is in effect by test-
; ing LPAGE to see if it is zero. Changed test to question to
; erase existing disk cross-reference file to handle lower-
; case as well as upper-case.
; - JRM
;
; 02/20/82 Changed code so that the size of the label that is refer-
; v20 enced in the cross-reference listing can be set at assembly
; time. The original program only allowed for 5 characters
; per label. This did not allow for separate unique labels
; where the uniqueness occurred after the first 5 characters.
; I tested this function for a length of 5, 8, and 10 chara-
; cters labels. It should work for any length of label. I
; also allowed the '$' character to be a valid character in a
; label. The equ LABSIZ was added and all other values and
; variables that are dependent on the size of the label are
; expressed using LABSIZ.
;
; Example: LSIZ EQU LABSIZ+3
;
; Added a disk file output option. The output disk file will
; use the filename of the input file and always have a file
; type of 'XRF'. This option is enabled by specifying a 'D'
; as the second parameter when executing the program. The
; user can optionally specify a different drive from the de-
; fault drive for the cross-reference disk output.
;
; Example: XREF FILENAME.ASM D
; XREF FILENAME.PRN B:D
; - JRM
;
;-----------------------------------------------------------------------
;
;
; Equates that can be changed
;
BUFSIZ EQU 16 ; In and out buffer size, 8 records = 1k
LABSIZ EQU 10 ; Number of characters per label
LPAGE EQU 0 ; Num lines per page if peject is true
LREFS EQU 10 ; References per output line
NREFS EQU 5 ; Number of references per ref tbl entry
;
;
; Equates that can't be changed
;
LSIZ EQU LABSIZ+3 ; Label table entry size
REFSZ EQU 2+(NREFS*2) ; Number of bytes in ref block
RSIZ EQU 05 ; Size of rtab table entry
;
BS EQU 08H ; Backspace
CR EQU 0DH ; Carriage return
EOF EQU 1AH ; EOF code
LF EQU 0AH ; Line feed
;
;
; Operating system equates
;
BOOT EQU 0000H ; Reboot entry point
BDOS EQU 0005H ; CP/M entry point
;
MEMSZ EQU 0006H ; End of memory pointer
TFCB EQU 005CH ; Trans. FCB
;
CONIN EQU 01 ; Console input function code
PSTRING EQU 09 ; Print string function code
OPEN EQU 15 ; Open function code
CLOSE EQU 16 ; Close file function code
DELETE EQU 19 ; Delete file function code
READ EQU 20 ; Read disk function code
WRITE EQU 21 ; Write disk function code
MAKE EQU 22 ; Make file function code
SETDMA EQU 26 ; Set DMA function code
;
;
; Main loop
;
;
ORG 100H
;
;
START: LXI SP,STACK ; Set stack pointer
CALL SETUP ; Initialize
;
MAIN: CALL GETBT ; Get a byte from source file
;
MAIN1: CALL CKNUM ; Test for numeric
JNC LNUM ; Yes, found a number, process
CALL CKALP ; Test for alphabetic
JNC LALPH ; Yes, process
LXI H,CTAB1 ; Point to character table
CALL LOOK ; Look up character in character table
JC MAIN ; Not found, ignore
PCHL ; Execute routine
;.....
;
;
; Finished
;
; Final label table print
;
DONE: MVI E,0CH ; Printer form feed character
CALL PBYT
MVI A,0FFH ;
STA LISTFLG ; CREF-list on always
LHLD LABBT ; Get label table bottom
MVI A,0FFH ; Check to see if there were...
CMP M ; Any labels in the program
JZ DLP4 ; No, don't print label table
SHLD LAB ; Set label pointer
LHLD LABTP ; Get label table top
MVI M,0FFH ; End off label table
;
DLP1: LHLD LAB ; Get label table pointer
CALL PLAB ; Print label
LHLD LAB
LXI D,LABSIZ+1 ; Offset to reference link
DAD D
MOV E,M
INX H
MOV D,M ; Get reference block address
XCHG ; Into HL
SHLD REF
CALL PREF ; Print references
LHLD LAB ; Get label table pointer
LXI D,LSIZ ; Size of symbol table entry
DAD D
SHLD LAB
MOV A,M ; Get byte
CPI 0FFH ; End of table?
JNZ DLP1 ; Loop
;
DLP2: MVI E,0CH ; Printer form feed character
CALL PBYT
LDA DISKOUT ; Get disk output switch
ORA A ; Disk output being used?
JZ DLP3 ; No, issue end msg & return to CP/M
LXI H,DISKBUF ; Get output disk buffer
LXI D,OFCB ; And out fcb
CALL DCLOSE ; And close output disk file
;
DLP3: LXI D,TFCB ; Close input file
MVI C,CLOSE
CALL BDOS
LXI D,DONEMSG ; Tell operator we're done
CALL PSOUT
JMP BOOT ; And return to CP/M
;.....
;
;
DLP4: LXI H,NOLABS ; Get no label message
MVI B,28 ; Number of characters in message
;
DLP5: MOV E,M ; Print the message
CALL PBYT
INX H
DCR B
JNZ DLP5
JMP DLP2 ; Go close files
;
;
; Label print routine
;
PLAB: MVI B,LABSIZ ; Label size
;
PLAB1: MOV E,M ; Get byte
CALL PBYT ; Print byte
INX H
DCR B
JNZ PLAB1
MVI E,' '
CALL PBYT ; Print 2 spaces
CALL PBYT
RET
;.....
;
;
; Reference print routine
;
PREF: MVI A,LREFS/NREFS ; Number of blocks to print on one line
STA NLINS ; To nlins
;
PREF1: LHLD REF ; Get reference block address
INX H
INX H ; Bump to first reference number
SHLD TEMP ; Save reference number address
MVI A,(REFSZ-2)/2 ; Number of ref slots
STA LABCT ; Save in symct
;
PREF2: LHLD TEMP ; Get reference slot address
MOV E,M
INX H
MOV D,M ; Get reference
LXI H,0000 ; Zero?
CALL CPHL
JZ CRLF ; Yes, done
PUSH D
MVI E,' '
CALL PBYT
POP D
MOV A,D
ANI 080H ; High bit set ?
JZ PREF3 ; Nope
;
MOV A,D ; If a label entry, show
ANI 07FH
MOV D,A ; Clear it
PUSH D
MVI E,'*'
CALL PBYT
POP D
JMP PREF4 ; Skip next space
;
PREF3: PUSH D
MVI E,' '
CALL PBYT
POP D
;
PREF4: XCHG ; Get number in HL
CALL DECOT ; Convert
CALL DECPNT ; Print it
LHLD TEMP ; Get reference slot address
INX H
INX H ; Bump to next slot
SHLD TEMP
LDA LABCT ; Get count
DCR A ; Decrement
STA LABCT
JNZ PREF2
LHLD REF ; Get ref block address
MOV E,M
INX H
MOV D,M ; Get link to next block
LXI H,0000
CALL CPHL ; Any more blocks?
JZ CRLF ; No, exit
;
XCHG ; Yes, set next block pointer in ref
SHLD REF
LDA NLINS
DCR A ; Decrement lines count
STA NLINS
JNZ PREF1 ; And print more on same line
CALL CRLF ; Print CR and LF
MVI B,LABSIZ+2 ; Indent continuation line...
;
PREF5: MVI E,' ' ; With spaces
CALL PBYT ; Print spaces
DCR B
JNZ PREF5 ; Print 6 spaces
JMP PREF
;.....
;
;
; Character parsing routines
;
LALPH: LXI H,SBUF ; Point to label buffer
MVI C,LABSIZ
MVI A,' ' ; Fill label...
;
LALX: MOV M,A ; With...
INX H ; Blanks
DCR C
JNZ LALX ; Clear label buffer
LXI H,SBUF
SHLD LABPT
MVI A,00
STA LABCT ; Reset label pointer+count
LDA CHAR ; Get character again
CALL GTLAB ; Collect identifier
;
LALC: CALL GETBT ; Get a byte from source file
CALL CKNUM ; Test for number
JNC LAL3 ; Yes, continue
CALL CKALP ; Test for alphabetic
JNC LAL3 ; Yes, continue
CALL CRES ; Test for reserved word
JC LAL1 ; No, continue
;
LAL0: CALL LINUP ; Up LINLAB
LDA CHAR ; Get character that ended ID
JMP MAIN1 ; Continue scan
;.....
;
;
;
LAL1: CALL FIND ; See if defined
JC LAL2 ; No, continue
CALL ADDRF ; Yes, add reference
JMP LAL0 ; Done
;.....
;
;
LAL2: CALL ENLAB ; Enter label definition
CALL ADDRF ; Add reference
JMP LAL0 ; Continue
;.....
;
;
LAL3: CALL GTLAB ; Collect identifier
JMP LALC ; Continue
;.....
;
;
LNUM: CALL GETBT ; Get byte
CALL CKNUM ; Test for numeric
JNC LNUM ; Yes, continue
CALL CKALP ; Test for alphabetic
JNC LNUM ; Yes, continue
JMP MAIN1 ; Continue with main scan
;.....
;
;
LQUOT: CALL GETBT ; Get a byte
CPI '''' ; See if string quote
JNZ LQUOT ; No, keep looping
CALL GETBT ; Get next byte
CPI '''' ; Test for doubles
JZ LQUOT ; Yes, start scan again
JMP MAIN1 ; No, continue in main scan
;.....
;
;
LSEMI: CALL GETBT ; Get a byte
CPI CR ; Wait for cr
JNZ LSEMI ; Continue
JMP MAIN1 ; Enter main loop
;.....
;
;
LCR: CALL PLINE ; Print line
LHLD LCNT ; Get line number
INX H ; Bump line number
SHLD LCNT ; Store
JMP MAIN
;.....
;
;
LLF: PUSH PSW ; Save char
LDA FTPRN ; Is it file...
ORA A ; Type prn?
JZ LLF2 ; Yes, skip 1rst 16 char
POP PSW ; Restore char
;
LLF1A: PUSH PSW ;
MVI A,0 ; Reset LINLAB
STA LINLAB
POP PSW
JMP MAIN
;.....
;
;
LLF2: POP PSW ; Restore character
MVI B,16 ; # of char to skip over
;
LLF3: CALL GETBT ; Get next byte
CPI CR ; Carriage return?
JZ LCR ; Yes, get next line
CPI EOF ; End of file now?
JZ DONE ; If yes, finish up
DCR B ; Skipped all char?
JNZ LLF3 ; No, continue skipping
JMP LLF1A ; Continue
;.....
;
;
LIGN: JMP MAIN ; Re-enter main loop
LSPC EQU LIGN
LTAB EQU LIGN
LDOL EQU LIGN
LDEL EQU LIGN
;
;
;----------------------------------------------------------------------
; subroutines
;
; Check for reserved word
;
CRES: LXI H,RTAB ; Point to reserved word table
SHLD TEMP ; Save in temp word
;
CRES1: LHLD TEMP ; Get table pointer
LXI D,SBUF ; Point to label
MVI B,5 ; Label size
;
CRES2: LDAX D ; Get label byte
CMP M ; Compare against table entry
RC ; Less, not in table
JNZ CRES3 ; Greater, get next table entry
INX D ; Bump pointers
INX H
DCR B ; Decrement byte count
JNZ CRES2 ; Keep testing
JMP CRES4 ; Found
;
CRES3: LHLD TEMP ; Get table pointer
LXI D,RSIZ ; Size of entry
DAD D ; Bump pointer
SHLD TEMP ; Store new pointer
MOV A,M ; Get table byte
CPI 0FFH ; End of table?
JNZ CRES1 ; No, loop
STC ; Set carry (not in table)
RET
;.....
;
;
CRES4: ORA A ; Reset carry
RET
;.....
;
;
; Find label in table
;
FIND: LHLD LABBT ; Get begin of sym table
SHLD LAB ; Set temp pointer
;
FIND1: LHLD LAB ; Get temp pointer
LXI D,SBUF ; Point to current label
MVI B,LABSIZ ; Label size
;
FIND2: LDAX D ; Get byte from sbuf
CMP M ; Compare to sym table byte
RC ; Greater, not in table
JNZ FIND3 ; Less, get next table entry
INX D ; Bump pointer
INX H ; Bump pointer
DCR B ; Decrement byte count
JNZ FIND2 ; Loop
RET ; True zero, found
;...
;
;
FIND3: LHLD LAB ; Get current pointer
LXI D,LSIZ ; Label table entry size
DAD D ; Bump pointer
XCHG ; Into de
LHLD LABTP ; Get top of label table
CALL CPHL ; Test for end of table
JZ FIND4 ; Yes, done
JC FERR ; Table overflow, error
XCHG ; Current pointer into HL
SHLD LAB ; Set current pointer
JMP FIND1 ; Loop
;
FIND4: STC ; Set carry for not found
LHLD LABTP ; Get current top
SHLD LAB ; Set current pointer
RET
;.....
;
;
FERR: LXI D,EMSG1 ; Label table error message
;
FERR1: CALL PSOUT ;
JMP BOOT ; Exit
;
FERR2: LXI D,EMSG6 ; No room for label table
JMP FERR1
;
;
; Add reference to ref table
;
ADDRF: LHLD LAB ; Get label pointer
LXI D,LABSIZ+1 ; Offset past label&flags
DAD D
MOV E,M
INX H
MOV D,M ; Get reference pointer
LXI H,0000
CALL CPHL ; Test for zero ref ptr
JZ BLDRF ; Yes, build reference entry
;
LINK1: XCHG ; Ref ptr in hl
MOV E,M ; Get ref link
INX H
MOV D,M ; Into de
DCX H ; Reposition hl
PUSH H ; Save ref ptr
LXI H,0000
CALL CPHL ; If link is zero
POP H
JNZ LINK1 ; Non zero, get next link
SHLD REF ; Save ref pointer
INX H
INX H ; Skip to first ref number
MVI B,(REFSZ-2)/2 ; Number of ref numbers/entry
;
LINK3: MOV E,M ; Get ref number
INX H
MOV D,M
DCX H ; Reposition
PUSH H ; Save ref num addr
LXI H,0000
CALL CPHL ; See if ref num is zero
POP H
JZ ENREF ; Yes, enter reference
INX H
INX H ; Skip to next ref num
DCR B ; Decrement count
JNZ LINK3 ; Try again at next slot
CALL ADBLK ; Add new ref block
LHLD REF ; Get ref pointer
INX H
INX H ; Skip to first ref slot
;
ENREF: PUSH H ; Save ref slot addr
LHLD LCNT ; Get line number
XCHG ; Into de
POP H ; Get ref slot addr
LDA LINLAB ; First label on line ?
ORA A
JNZ ENREF1 ; Nope
CALL LINUP ; Up LINLAB
MOV A,D
ADI 080H
MOV D,A ; Set high bit
;
ENREF1: MOV M,E
INX H
MOV M,D ; Store line ref
RET ; Done
;.....
;
;
; Build reference table block
;
BLDRF: LHLD LAB ; Get label pointer
LXI D,LABSIZ+1 ; Offset to ref pointer
DAD D
SHLD REF ; Set temp ref pointer to here
CALL ADBLK ; Add block
LHLD REF ; Get real ref pointer
INX H
INX H ; Position to first ref slot
JMP ENREF ; Add reference
;
ADBLK: LHLD REFBT ; Get ref bottom
LXI D,REFSZ ; Subtract ref size
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A
SHLD TEMP ; Save new ref bottom
XCHG ; Into de also
LHLD LABTP ; Get label top
CALL CPHL ; Check for bump
JZ FERR2 ; Yes, no room
JNC FERR2 ; No room
LHLD TEMP ; Get ref bottom
XCHG ; Into DE
LHLD REF ; Get ref pointer
MOV M,E ; Set link
INX H
MOV M,D ; To new reference check
LHLD TEMP ; Get new reference block address
SHLD REF ; Store in reference
MVI B,REFSZ ; Size of ref block
MVI A,0
;
ADB2: MOV M,A ; Zero the ref block
INX H
DCR B
JNZ ADB2
LHLD TEMP ; Get new ref bottom
SHLD REFBT ; Set refbt
RET
;.....
;
;
; Enter label in label table
;
ENLAB: LHLD LAB ; Get label pointer
XCHG ; Into DE
LHLD LABTP ; Get label table top
CALL CPHL ; Check for end of table
JZ NWLAB ; Yes, add label at end
LXI D,LSIZ ; Label table entry size
DAD D ; Calculate new end of table
XCHG ; Into de
LHLD REFBT ; Reference table bottom
CALL CPHL ; Test for table overflow
LXI D,EMSG7 ; Address of error msg in of overflow
JZ FERR1 ; Full, error
JC FERR1 ; Yes, error
LHLD LABTP ; Get table top
LXI D,LSIZ-1 ; Bump to end of entry
DAD D
SHLD TO ; Store in to address
LXI D,LSIZ
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A ; Subtract size of one entry
SHLD FROM ; Store as from address
LHLD LAB ; Get current pointer
SHLD LIMIT ; Store as limit address
CALL MVUP ; Move table up in memory
;
NWLAB: LHLD LAB ; Get current pointer
LXI D,SBUF ; Point to label
MVI B,LABSIZ ; Size of label
CALL MOVE ; Copy label to table
MVI A,0
MOV M,A
INX H
MOV M,A
INX H
MOV M,A ; Set pointers to 0000
LHLD LABTP ; Get label table top
LXI D,LSIZ ; Get label entry size
DAD D ; Bump
SHLD LABTP ; Store new top
RET
;.....
;
;
; Move label table up
;
MVUP: LHLD TO ; Get to pointer
MOV B,H
MOV C,L ; Into BC
LHLD FROM ; Get from pointer
XCHG ; Into DE
LHLD LIMIT ; Get limit address
;
MVUP2: LDAX D ; Get from byte
STAX B ; Store at to address
CALL CPHL ; Compare from to limit
RZ ; Exit if done
DCX B ; Decrement to
DCX D ; Decrment from
JMP MVUP2 ; Loop
;.....
;
;
; General purpose move routine
;
MOVE: LDAX D ; Get byte
MOV M,A ; Store byte
INX D
INX H ; Bump pointers
DCR B ; Decrement count
JNZ MOVE ; Loop
RET
;.....
;
;
; Binary to decimal conversion
;
DECOT: LXI D,DEC
XCHG
LXI B,10000
CALL DIG
LXI B,1000
CALL DIG
LXI B,100
CALL DIG
LXI B,10
CALL DIG
LXI B,1
CALL DIG
RET
;.....
;
;
DIG: MVI M,'0'
;
DI0: MOV A,E
SUB C
MOV E,A
MOV A,D
SBB B
MOV D,A
JM DI2
INR M
JMP DI0
;
DI2: MOV A,E
ADD C
MOV E,A
MOV A,D
ADC B
MOV D,A
INX H
RET
;.....
;
;
; Print number string in DEC
;
DECPNT: LXI H,DEC+1 ; Point to dec string
;
DCPNT1: MOV E,M ; Get string byte
MOV A,E
CPI '$' ; Done?
RZ ; Yes
;
CALL PBYT ; Print byte
INX H ; Bump pointer
JMP DCPNT1
;.....
;
;
; Up LINLAB after label found
;
LINUP: PUSH PSW
LDA LINLAB
INR A
STA LINLAB ; Found first separator
POP PSW
RET
;.....
;
;
; Test for alphabetic character
;
CKALP: CPI '$' ; Treat '$' like a char
RZ
CPI 'A' ; Ascii 'a'
RC ; No, exit
CPI 'Z'+1
CMC
RET
;.....
;
; Test for numeric character
;
CKNUM: CPI '0'
RC
CPI '9'+1
CMC
RET
;.....
;
;
; Look up character in parse table
;
LOOK: LXI D,0003 ; Table entry size
MOV B,A ; Argument byte in b
;
LOOK2: MOV A,M ; Get table byte
CPI 0FFH ; End of table?
JZ LOOKN ; Yes, not found
CMP B ; Compare
JZ LOOKY ; Found
DAD D ; Bump pointer
JMP LOOK2 ; Loop
;
LOOKN: STC ; Carry = not found
RET
;.....
;
;
LOOKY: INX H ; Skip to table byte
MOV E,M
INX H
MOV D,M ; Table entry in de
XCHG ; Into hl
RET
;.....
;
;
; Print source line with number
;
PLINE: LHLD LCNT ; Get line number
CALL DECOT ; Convert to decimal
CALL DECPNT ; Print it
;
PL1: MVI E,' '
CALL PBYT
LDA FTPRN
ORA A
JZ PL11
MVI E,' '
CALL PBYT
;
PL11: LXI H,PBUF ; Point to print buffer
XRA A
STA COL ; Set column count
;
PL41: MOV E,M ; Get byte
MOV A,E
CPI CR ; Done?
JZ PL5
CPI LF ; Lf?
JZ PL4A ; Yes, ignore
CPI 09H ; Tab?
JNZ PL42 ; No, continue
PUSH H ; Save hl
;
PL43: MVI E,' '
CALL PBYT ; Print space
LXI H,COL
INR M
MOV A,M
ANI 07H ; Modulo 8
JNZ PL43
POP H
JMP PL4A
;
PL42: LDA COL
INR A
STA COL
CALL PBYT ; Print byte
;
PL4A: INX H
JMP PL41
;
PL5: CALL CRLF ; Print cr,lf
LXI H,PBUF
SHLD LPNT ; Reset line pointer
RET
;.....
;
;
; Collect label in label buffer
;
GTLAB: MOV B,A ; Save char
LDA LABCT ; Get label count
CPI LABSIZ ; Max?
RNC ; Yes, done
INR A
STA LABCT
LHLD LABPT
MOV M,B
INX H ; Bump label pointer
SHLD LABPT
RET
;.....
;
;
; Printer interfaces
;
; Print a single byte
;
PBYT: PUSH B
PUSH D
PUSH H
PUSH PSW
;
LDA LISTFLG ; Listing on ?
ORA A
JZ PBYT3 ; No listing
LDA DISKOUT ; Disk output...
ORA A ; In effect?
JNZ DBYT ; Yes, go write to disk
MVI C,05
LDA CONSOLE ; Get console out switch
ORA A ; Console output?
JZ PBYT2 ; No, print output
MVI C,2 ; Console output
;
PBYT2: CALL BDOS
;
PBYT3: MVI C,11 ; Check console status
CALL BDOS
ORA A ; If zero, ok
JZ PBYTX ; Exit
MVI C,1
CALL BDOS ; Read console char
CPI 3
JZ BOOT ; Abort if ^C, otherwise ignore
;
PBYTX: POP PSW
POP H
POP D
POP B
RET
;.....
;
;
; Put output character into disk buffer - input=e (output character)
;
DBYT: MOV A,E ; Save char to be put in buffer
LHLD DSKCNT ; Get num of char left in buf
XCHG ; Put num in d,e
LHLD DCHAR ; Point to next char in buf
MOV M,A ; Put char in disk buf
DCR E ; At end of buf?
JNZ DBYT1 ; No, don't write buffer
DCR D ; At end of buf?
JZ PUTREC ; Yes, go write buffer
;
DBYT1: INX H ; Point to next char in buf
SHLD DCHAR ; Save next pos
XCHG ; Put num of char left in h,l
SHLD DSKCNT ; Save num of remaining char
JMP PBYT3 ; Go check console status
;.....
;
;
; Write out disk buffer to disk
;
PUTREC: LXI H,DISKBUF ; Address of disk buffer
SHLD BUFADR ; Save it for later dma's
MVI B,BUFSIZ ; Number of disk sectors to write
;
PUTRC2: PUSH B ; Save sector count
LHLD BUFADR ; Get disk buffer address
XCHG ; Put it in d,e for dma
LXI H,80H ; Put 128 h,l
DAD D ; Add 128 to disk buf adr for next dma
SHLD BUFADR ; Save it for next dma
MVI C,SETDMA ; Point dma to...
CALL BDOS ; Correct buffer
LXI D,OFCB ; Get output disk fcb
MVI C,WRITE ; Write sector...
CALL BDOS ; To disk
ORA A ; Was write successfull?
POP B ; Restore num of sectors left
LXI D,EMSG4 ; Get err msg in case write failed
JNZ FERR1 ; Disk write failed, display err msg, quit
DCR B ; Written 16 sectors yet?
JNZ PUTRC2 ; No, continue writing disk sectors
LXI H,BUFSIZ*128 ; Put disk buffer size into HL
SHLD DSKCNT ; Set num of char left in buf to buffer size
LXI H,DISKBUF ; Point to front...
SHLD DCHAR ; Of disk buffer
JMP PBYT3 ; Go check console status for ^C
;.....
;
;
; Issue CR, LF and test page
;
CRLF: MVI E,CR
CALL PBYT
MVI E,LF
CALL PBYT
LDA LINES
INR A
STA LINES ; Increment line count
MVI A,LPAGE ; Get number of lines
ORA A ; Is it zero?
LDA LINES
RZ ; Yes, return
CPI LPAGE ; Test line count
RNZ
MVI E,0CH ; Printer form feed character
CALL PBYT
;.....
;
;
; Character parsing table
;
CTAB1: DB CR
DW LCR
DB LF
DW LLF
DB ''''
DW LQUOT
DB ';'
DW LSEMI
DB ' '
DW LSPC
DB 09H
DW LTAB
DB '$'
DW LDOL
DB '('
DW LDEL
DB ')'
DW LDEL
DB '+'
DW LDEL
DB '-'
DW LDEL
DB '*'
DW LSEMI
DB '/'
DW LDEL
DB ','
DW LDEL
DB ':'
DW LDEL
DB EOF
DW DONE
DB 0FFH
DW 0000H
;.....
;
;
; Reserved word table
;
RTAB: DB '$ ','8080 '
DB 'A ','ACI ','ADC ','ADD ','ADI '
DB 'AF ','ANA ','AND ','ANI ','ASEG '
DB 'B ','BC ','BIT '
DB 'C ','CALL ','CC ','CCF ','CM '
DB 'CMA ','CMC ','CMP ','CNC ','CNZ '
DB 'COMME','COMMO','COND ','CP ','CPD '
DB 'CPDR ','CPE ','CPI ','CPL ','CPO '
DB 'CSEG ','CZ '
DB 'D ','DAA ','DAD ','DB ','DC '
DB 'DCR ','DCX ','DE ','DEC ','DEFB '
DB 'DEFL ','DEFM ','DEFW ','DI ','DJNZ '
DB 'DS ','DSEG ','DW '
DB 'E ','EI ','ELSE ','END ','ENDC '
DB 'ENDIF','ENDM ','ENTRY','EQ ','EQU '
DB 'EX ','EXX ','EXITM','EXT ','EXTRN'
DB 'GE ','GLOBA','GT '
DB 'H ','HL ','HIGH ','HALT '
DB 'IF ','IFB ','IFDEF','IFE ','IFF '
DB 'IFNB ','IFNDE','IFT ','IF1 ','IF2 '
DB 'IM ','IN ','INC ','INCLU','IND '
DB 'INDR ','INIR ','INR ','INX ','IRP '
DB 'IRPC ','IX ','IY '
DB 'JC ','JM ','JMP ','JNC ','JNZ '
DB 'JP ','JPE ','JPO ','JR ','JZ '
DB 'L ','LALL ','LD ','LDA ','LDAX '
DB 'LDD ','LDDR ','LDI ','LDIR ','LE '
DB 'LHLD ','LIST ','LOCAL','LOW ','LT '
DB 'LXI '
DB 'M ','MACRO','MOD ','MOV ','MVI '
DB 'NAME ','NC ','NE ','NEG ','NOP '
DB 'NOT ','NUL ','NZ '
DB 'OR ','ORA ','ORG ','ORI ','OTDR '
DB 'OTIR ','OUT ','OUTI ','OUTD '
DB 'P ','PAGE ','PCHL ','PE ','PO '
DB 'POP ','PRINT','PSW ','PUBLI','PUSH '
DB 'RADIX','RAL ','RAR ','RC ','REPT '
DB 'RES ','RET ','RETI ','RL ','RLA '
DB 'RLC ','RLCA ','RLD ','RM ','RNC '
DB 'RNZ ','RP ','RPE ','RPO ','RR '
DB 'RRA ','RRC ','RRCA ','RRD ','RST '
DB 'RZ '
DB 'SALL ','SBB ','SBC ','SBI ','SCF '
DB 'SET ','SHL ','SHLD ','SHR ','SLA '
DB 'SP ','SPHL ','SRA ','SRL ','STA '
DB 'STAX ','STC ','SUB ','SUBTT','SUI '
DB 'TITLE'
DB 'XALL ','XCHG ','XLIST','XOR ','XRA '
DB 'XRI ','XTHL '
DB 'Z ','Z80 '
DB 0FFH ; End of reserved word table
;.....
;
;
; Routine to open a disk file
; input: DE=A(FCB)
;
FOPEN: MVI C,OPEN ; Open code
CALL BDOS ; Issue open
CPI 0FFH ; Error?
RNZ ; No error
LXI D,EMSG0
JMP FERR1
;.....
;
;
; Routine to close output disk cross-reference file
; input: DE=ADDR(FCB)
; HL=ADDR(BUFFER)
;
DCLOSE: PUSH D ; Save fcb address
PUSH H ; Save buffer address
LHLD DSKCNT ; Put number of char left...
XCHG ; In buffer into d,e
LHLD DCHAR ; Point to next char in output buf
MVI A,1AH ; Put a control z in accum
;
DCLSE2: MOV M,A ; Fill...
INX H ; Rest of...
DCR E ; Buffer...
JNZ DCLSE2 ; With...
DCR D ; Control z's.
JNZ DCLSE2
POP H ; Point to...
;
DCLSE4: XCHG ; Output buffer
LXI H,128 ; Put 128 into h,l
DAD D ; Add 128 to disk buf addr for next dma
SHLD BUFADR ; Save it for next dma after this one
MVI C,SETDMA ; Disk buffer for...
CALL BDOS ; Last disk write
POP D ; Do last...
PUSH D ; (d,e contains ofcb)...
MVI C,WRITE ; Disk...
CALL BDOS ; Write
;
;
; Check to see if last record has been written. Do this by comparing
; the address of the next available character to the address of the buf-
; fer for the next disk write. If the address of the next available
; character is equal to or greater, close the file.
;
LHLD DCHAR ; Put high order address
XCHG ; Of last char+1...
MOV A,D ; Into accum
LHLD BUFADR ; Get addr of next disk buffer
CMP H ; Compare to last char+1 in buffer
JC DCLSE5 ; If next addr is greater, close file
JNZ DCLSE4 ; If not equal, continue
MOV A,E ; Put low order address of last char+1
CMP L ; Into accum and test
JNC DCLSE4 ; If not less, do another write
;
DCLSE5: POP D ; Close the...(d,e contains ofcb)
MVI C,CLOSE ; Output disk
CALL BDOS ; Cross ref file
CPI 0FFH ; Close successfull?
RNZ ; Yes, return
LXI D,EMSG5 ; No, display error msg...
JMP FERR1 ; And quit
;.....
;
;
; Rroutine to read a byte
; outputs: A=BYTE
;
GETBT: LXI H,TBUF+(BUFSIZ*128) ; End of input buf addr
XCHG ; Buffer end addr. in de
LHLD INPTR ; Current pointer in hl
CALL CPHL ; Test for end of buffer
CZ GETREC ; Yes, read disk records
MOV A,M ; Get byte
INX H ; Bump pointer
SHLD INPTR ; Save pointer
ORA A ; Clear carry
JMP SAVBT
;.....
;
;
; Save byte in line buffer
;
SAVBT: LHLD LPNT ; Get line pointer
MOV M,A ; Save byte
INX H ; Bump pointer
SHLD LPNT ; Save pointer
CALL LWRUPR ; Convert lower to upper case
STA CHAR ; Save char in char
RET
;.....
;
;
GETREC: LDA CONSOLE ; Console on ?
ORA A
JNZ GTREC1 ; Then he sees progress
LHLD LCNT ; Line-count
CALL DECOT ; Into ASCII
LXI D,DECERA ; Erase area
CALL PSOUT
LXI D,DEC ; ASCII linecount
CALL PSOUT ; To show progress
;
GTREC1: MVI B,BUFSIZ ; Number of sectors to read
LXI H,TBUF ; Get address of disk input buffer
SHLD IDADDR ; Initialize current buffer address
;
GETRC2: LHLD IDADDR ; Get addr of input buffer
XCHG ; Put it in DE
LXI H,128 ; Add 128 to input buf
DAD D ; Addr for read after next
SHLD IDADDR ; Save it read after next
PUSH B ; Save sector count
PUSH D ; Save current ptr in case EOF occurrs
MVI C,SETDMA ; Point to input buffer...
CALL BDOS
MVI C,READ ; Read code
LXI D,TFCB ; FCB address
CALL BDOS ; Issue read
POP D ; Restore current buf pointer
POP B ; Restore sector count
CPI 00 ; Error?
JNZ GETRC4 ; Yes
DCR B ; Read all of the sectors?
JNZ GETRC2 ; No, continue reading
GETRC3: LXI H,TBUF ; Reset buffer pointer
SHLD INPTR
RET ; Return to caller
;...
;
;
GETRC4: XCHG ; Point to first char past buf
MVI M,26H ; Put two...
INX H ; Control z's
MVI M,26H ; After last rec in file
JMP GETRC3 ; Go reset buffer pointer
;.....
;
;
; Converts lower to upper case
; input: a=byte(upper/lower
; outputs: a=byte upper
;
LWRUPR: CPI 'A'+20H ; Is it upper case?
CMC ; Complement carry
RNC ; Yes, return with carry reset
CPI 'Z'+21H ; Over lower case 'z'?
RNC ; No, return no carry
SUI 20H ; Convert to upper case
RET
;.....
;
;
;PSOUT prints string in D
;
PSOUT: MVI C,PSTRING
CALL BDOS ; Print String
RET
;.....
;
;
; Routine to compare HL vs DE
; output: HL=DE, zero=on
; HL<>DE, zero=off
;
CPHL: MOV A,H
CMP D
RNZ
MOV A,L
CMP E
RET
;.....
;
;
; DATA
;
EMSG1: DB CR,LF,'Label table error',CR,LF,'$'
EMSG2: DB CR,LF,'Failed to delete existing cross reference file'
DB CR,LF,'$'
EMSG3: DB CR,LF,'Failed to create cross reference file',CR,LF,'$'
EMSG4: DB CR,LF,'Disk write failed - Out of space?',CR,LF,'$'
EMSG5: DB CR,LF,'Close failed on disk cross reference file'
DB CR,LF,'$'
EMSG6: DB CR,LF,'++ERROR++ Not enough memory for label table'
DB CR,LF,'$'
EMSG7: DB CR,LF,'++ERROR++ Label table overflow?',CR,LF,'$'
DONEMSG:DB CR,LF,'Cross-reference list is done',CR,LF,'$'
NOLABS: DB CR,LF,'No Labels in this Program'
CONCRLF:DB CR,LF,'$'
OFCB: DB 0 ; Disk output FCB, default drive
DS 8 ; File name
DB 'XRF' ; File type
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
DCHAR: DW DISKBUF ; Pointer for disk buffer
BUFADR: DS 2 ; Pointer to disk output buffer for dma
IDADDR: DS 2 ; Pointer to disk input buffer for dma
DSKCNT: DW BUFSIZ*128 ; Number of char left in disk buffer
INPTR: DW TBUF+(BUFSIZ*128) ; Pointer to char in input buffer
DISKBUF:DS BUFSIZ*128 ; Output disk buffer
TBUF: DS BUFSIZ*128 ; Disk input buffer
;
;
CHAR: DS 1
COL: DS 1
FROM: DS 2 ; Move pointer
LAB: DS 2 ; Current label table address
LABBT: DS 2 ; Label table bottom address
LABTP: DS 2 ; Label table top address
LCNT: DS 2 ; Line counter
LIMIT: DS 2 ; Limit pointer
LINLAB: DS 1 ; 0 if first label on line
LPNT: DS 2
REF: DS 2 ; Current reference table address
REFBT: DS 2 ; Reference table bottom address
REFTP: DS 2 ; Reference table top address
TO: DS 2 ; To pointer
DEC: DS 5
DB '$'
;
DECERA: DB BS,BS,BS,BS,BS,'$' ; Erase string for Line-Nr display
PBUF: DS 132
LABCT: DS 1
LABPT: DS 2
SBUF: DS LABSIZ ; Label buffer
NLINS: DB 0 ; Buffers to print on line
LINES: DB 0 ; Print line count
;
CONSOLE:DB 0 ; Console output switch
DISKOUT:DB 0 ; Disk output switch
LISTFLG:DB 0 ; 0=no source listing
FTPRN: DB 1 ; Prn file type
TEMP: DS 2 ; Temp save word
DS 64 ; Stack can have up to 32 addresses
STACK EQU $
;.....
;
;
; Label table area
;
; The label table must be the last byte before ONCE ONLY CODE - XREF
; is NOT RESTARTABLE
;
;
ORG $
;
;
LABT: DB 0FFH
;
LOGO: DB CR,LF,'CP/M assembler cross-reference list v27'
DB CR,LF,'$'
;
MSG1: DB ' disk cross-reference file exists, keep it (y/n) ? '
DB '$'
;
MSG2: DB ' like to have a line-numbered .XRF listing (y/n) ? '
DB '$'
;
EMSG0: DB CR,LF,'++ Can''t find that file ++',CR,LF,'$'
;
;
;
HELP: DB CR,LF,'This program can be used to create a cross-'
DB 'reference listing',CR,LF,'of CP/M assembler programs.'
DB ' The input can be either the assembler',CR,LF
DB 'language source code (FILENAME.ASM) or the assembly '
DB 'listing (FILENAME.PRN).',CR,LF
DB 'The output can be printed on the CP/M list device, '
DB 'displayed on',CR,LF
DB 'the CRT, or written to disk (file type will be '
DB '.XRF). It is',CR,LF,'invoked by keying:',CR,LF,LF
DB 09H,'XREF FILENAME.ASM (Output on list device)'
DB CR,LF,09H,'XREF FILENAME.PRN CRT (Output on the '
DB 'CRT)',CR,LF,09H,'XREF FILENAME.ASM D (Output on '
DB 'disk-default drive)',CR,LF,09H,'XREF FILENAME.PRN B:D'
DB ' (Output on disk-drive specified)'
DB CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,'$'
;.....
;
;
; Setup or initialization
;
SETUP: LXI D,LOGO ; Get program logo messagew
CALL PSOUT ; Display it
LDA TFCB+1 ; Get first character of file name
CPI ' '
JZ SETUP0
CPI '?' ; Help function?
JNZ SETUP1 ; No, go check input file type
;
SETUP0: LXI D,HELP ; Display help message
JMP FERR1
;...
;
;
SETUP1: MVI A,0
STA LISTFLG ; No listing
LDA TFCB+9 ; Get first character of file type
CPI 'P' ; Is it type .PRN?
JNZ SETUP2 ; No, don't set switch
LDA TFCB+10 ; Get 2nd character of file type
CPI 'R'
JNZ SETUP2
LDA TFCB+11 ; Get 3rd character of file type
CPI 'N'
JNZ SETUP2
XRA A
STA FTPRN ; Turn on .PRN file type
;
SETUP2: LDA TFCB+17 ; Get 1st character of 2nd FCB
CPI 'C' ; Output to console?
JNZ SETUP3 ; No, don't turn on switch
LDA TFCB+18 ; Get 2nd character of 2nd FCB
CPI 'R' ; Output to CRT?
JNZ SETUP3 ; If not, exit
MVI A,0FFH ; else turn on CRT
STA CONSOLE
JMP SETUP5 ; Go open input file
;
SETUP3: LDA TFCB+17 ; Get 1st character of 2nd FCB
CPI 'D' ; Output to be written to disk?
JNZ SETUP5 ; If not, exit
MVI A,0FFH
STA DISKOUT ; Turn on disk output switch
LDA TFCB+16 ; Get output file drive number
STA OFCB ; Move to output FCB
LXI D,TFCB ; Point to FCB
CALL FOPEN ; Open disk input file
LXI D,TFCB+1 ; Point to input file name
MVI B,8 ; Length of file name
LXI H,OFCB+1 ; Point to output FCB file name
CALL MOVE ; Move input file name to output FCB
LXI D,OFCB ; Does output file already exist?
MVI C,OPEN
CALL BDOS
CPI 0FFH ; Open succeed?
JZ SETUP4 ; No, file does not exist
LXI D,OFCB ; Close...
MVI C,CLOSE ; The open...
CALL BDOS ; File.
;
LXI D,MSG1 ; Want to keep the old file?
CALL PSOUT
MVI C,CONIN ; Get the answer
CALL BDOS
ANI 05FH ; Make upper case
CPI 'Y' ; Operator say yes, keep it?
JZ BOOT ; If, yes, exit, done
LXI D,CONCRLF ; Write CRLF to console
CALL PSOUT
LXI D,OFCB ; Point to FCB to delete file
MVI C,DELETE ; Delete the file
CALL BDOS
CPI 0FFH ; Delete succeed?
LXI D,EMSG2 ; If not, show error message
JZ FERR1
;
SETUP4: LXI D,OFCB ; Point to output FCB
MVI C,MAKE ; Create new...
CALL BDOS ; Cross reference file.
CPI 0FFH ; Create succeed?
LXI D,EMSG3 ; Get err msg in case of failure
JZ FERR1 ; Create failed, print msg & quit
LXI H,DISKBUF ; Get addr of disk buffer
SHLD DCHAR ; Init disk char pointer
;
SETUP5: LXI D,TFCB ; Point to fcb
CALL FOPEN ; Open fcb
LXI D,MSG2 ; "Want Listing.."
CALL PSOUT
MVI C,CONIN
CALL BDOS ; Get answer
ANI 05FH ; Make upper case
CPI 'Y'
JNZ SETUP6 ; No listing
MVI A,0FFH
STA LISTFLG ; Wants listing
;
SETUP6: LXI D,CONCRLF ; Write CRLF to console
CALL PSOUT
LXI H,PBUF
SHLD LPNT ; Set print pointer
LXI H,00001 ; Set line counter...
SHLD LCNT ; To one.
LXI H,LABT ; Get address of label table
SHLD LAB
SHLD LABBT
SHLD LABTP ; Set label table pointers
LHLD MEMSZ ; Get available memory address
DCX H
SHLD REF
SHLD REFBT
SHLD REFTP ; Set reference table pointers
RET
;.....
;
;
END START