home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG078.ARK
/
XREFPRN.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
23KB
|
1,065 lines
;15/2/80: 1345
;************************************************;
; INTEL ASSEMBLER
; CROSS REFERENCE PROGRAM
; VERSION 2.1
; ORIGINAL BY: JEFF KRAVITZ (REF. 8.27)
; MODIFIED BY: P.P.H. LEE, TO WORK WITH *.PRN FILES
; GENERATED BY THE CP/M ASM ASSEMBLER, ALSO
; HANDLES NON-EXISTING FILES CORRECTLY, AND
; HAVE BIGGER DISK BUFFER.
; PAGE LENGTH CHANGED TO 60 LINES PER PAGE, AND
; NUMBER OF REFERENCES PER LINE IN THE CROSS
; REFERENCE LIST INCREASED FROM 8 TO 12.
; DATA AREAS REARRANGED AND SYMT INITIALIZED
; DURING EXECUTION, GIVING SHORTER COM FILE.
; PRINTS DIRECTLY TO THE LOGICAL LIST DEVICE
; VIA THE BIOS LIST VECTOR.
; LIMIT OF SYMBOL LENGTH INCREASED FROM 5 TO 7
; CHARACTERS.
;
;MODIFIED 1/3/81 BY WARD CHRISTENSEN TO CHANGE
;LABEL "LINK" TO ALLOW ASSEMBLY UNDER "LINKASM"
;WHICH USES "LINK" AS A PSEUDO-OP.
;
;************************************************;
;********************************;
; MAIN LOOP
;********************************;
ORG 100H ;ORIGIN ADDRESS
XREF: LXI SP,STACK ;SET STACK POINTER
LHLD 1 ;GET WARM BOOT ADDRESS
LXI D,3
DAD D ;GET CONSOLE STATUS VECTOR
SHLD CONST+1 ;SAVE IT
DAD D ;GET CONSOLE IN VECTOR
SHLD CONIN+1 ;SAVE IT
DAD D
DAD D ;GET LIST VECTOR
SHLD LIST+1 ;SAVE IT
MVI A,0FFH ;INITIALIZE SYMT
STA SYMT
CALL SETUP ;INITIALIZE
XREF1: CALL GETBYT ;GET RID OF LEADING
CPI 0DH ;CR
JZ XREF1 ;AND
CPI 0AH ;LF
JZ XREF1
JMP MAIN1 ;SKIP AROUND
MAIN: CALL GETBYT ;GET A BYTE FROM SOURCE FILE
MAIN1: CALL SAVBYT ;SAVE BYTE IN PRINT BUFFER
MAIN2: CALL CHKNUM ;TEST FOR NUMERIC
JNC LNUM ;YES, FOUND A NUMBER, PROCESS
CALL CHKALP ;TEST FOR ALPHABETIC
JNC LALPH ;YES, PROCESS
LXI H,CPTBL ;POINT TO CHARACTER TABLE
CALL LOOK ;LOOK UP CHAR IN CHAR TABLE
JC MAIN ;NOT FOUND, IGNORE
PCHL ;EXECUTE ROUTINE
;********************************;
; FINAL SYMBOL TABLE PRINT
;********************************;
DONE: LDA LINES ;CHECK IF ALREADY ON
ORA A ;NEW PAGE
JZ DONE2 ;BRIF IS
MOV B,A ;SAVE LINE NUMBER
MVI E,0AH ;FINISH DOING CURRENT PAGE
DONE1: CALL PRBYT ;BY PRINTING
MOV A,B ;THE REQUIRED
INR A ;NUMBER OF
MOV B,A ;LINE FEEDS
CPI 60 ;FINISHED?
JC DONE1 ;BRIF NOT
CALL PAGE ;ELSE ISSUE PAGE EJECT
DONE2: LXI H,XRFHD ;AND PRINT OUT
MVI B,16 ;THE CROSS REFERENCE
DONE3: MOV E,M ;HEADING
CALL PRBYT ;BEFORE PRINTING
INX H ;THEM
DCR B
JNZ DONE3
CALL CRLF
CALL CRLF
LHLD SYMBT ;GET SYMBOL TABLE BOTTOM
SHLD SYM ;SET SYMBOL POINTER
LHLD SYMTP ;GET SYMBOL TABLE TOP
MVI M,0FFH ;END OFF SYMBOL TABLE
DLP1: LHLD SYM ;GET SYMBOL TABLE POINTER
CALL PRSYM ;PRINT SYMBOL
LHLD SYM
LXI D,SYMSZ ;OFFSET TO REF LINK
DAD D
MOV E,M
INX H
MOV D,M ;GET REF BLOCK ADDR
XCHG ;INTO HL
SHLD REF
CALL PREFS ;PRINT REFERENCES
LHLD SYM ;GET SYMBOL TABLE POINTER
LXI D,STESZ ;SIZE OF SYM TABLE ENTRY
DAD D
SHLD SYM
MOV A,M ;GET BYTE
CPI 0FFH ;END OF TABLE?
JNZ DLP1 ;BRIF NOT
JMP BOOT ;ELSE REBOOT CP/M
;********************************;
; SYMBOL PRINT ROUTINE
;********************************;
PRSYM: MVI B,SYMSZ ;SYMBOL SIZE
PRSYM2: MOV E,M ;GET BYTE
CALL PRBYT ;PRINT BYTE
INX H
DCR B
JNZ PRSYM2
MVI E,' '
CALL PRBYT ;PRINT 2 SPACES
CALL PRBYT
RET
;********************************;
; REFERENCE PRINT ROUTINE
;********************************;
PREFS: LHLD REF ;GET REF BLOCK ADDR
INX H
INX H ;BUMP TO FIRST REF NUMBER
SHLD TEMP ;SAVE REF NUM ADDR
MVI A,(REFSZ-2)/2 ;NUMBER OF REF SLOTS
STA SYMCT ;SAVE IN SYMCT
PREF: LHLD TEMP ;GET REF SLOT ADDR
MOV E,M
INX H
MOV D,M ;GET REF
LXI H,0000 ;ZERO?
CALL CPHL
JZ PREFX ;YES, DONE
XCHG ;GET NUM IN HL
CALL DECOT ;CONVERT
LXI H,DEC ;POINT TO DEC STRING
MVI M,' ' ;BLANK LEADING ZERO
MVI B,5
PREF2: MOV E,M
CALL PRBYT ;PRINT BYTE
INX H
DCR B
JNZ PREF2 ;PRINT REFERENCE NUMBER
LHLD TEMP ;GET REF SLOT ADDR
INX H
INX H ;BUMP TO NEXT SLOT
SHLD TEMP
LDA SYMCT ;GET COUNT
DCR A ;DECREMENT
STA SYMCT
JNZ PREF
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 PREFX ;NO, EXIT
XCHG ;YES, SET NEXT BLOCK POINTER
SHLD REF ;IN REF
CALL CRLF ;PRINT CR,LF
MVI B,SYMSZ+2
PREF3: MVI E,' '
CALL PRBYT ;PRINT SPACES
DCR B
JNZ PREF3 ;PRINT 6 SPACES
JMP PREFS
PREFX: CALL CRLF ;PRINT CR,LF
RET
;********************************;
; CHARACTER PARSING ROUTINES
;********************************;
LALPH: LXI H,SBUF ;POINT TO SYMBOL BUFFER
MVI C,SYMSZ
MVI A,' '
LALX: MOV M,A
INX H
DCR C
JNZ LALX ;CLEAR SYMBOL BUFFER
LXI H,SBUF
SHLD SYMPT
MVI A,00
STA SYMCT ;RESET SYMBOL POINTER+COUNT
LDA CHAR ;GET CHARACTER AGAIN
CALL GETSYM ;COLLECT IDENTIFIER
LALC: CALL GETBYT ;GET A BYTE FROM SOURCE FILE
CALL SAVBYT ;SAVE BYTE IN PRINT BUFFER
CALL CHKNUM ;TEST FOR NUMBER
JNC LAL3 ;YES, CONTINUE
CALL CHKALP ;TEST FOR ALPHABETIC
JNC LAL3 ;YES, CONTINUE
CALL CKRES ;TEST FOR RESERVED WORD
JC LAL1 ;NO, CONTINUE
LAL0: LDA CHAR ;GET CHARACTER THAT ENDED ID
JMP MAIN2 ;CONTINUE SCAN
LAL1: CALL FIND ;SEE IF DEFINED
JC LAL2 ;NO, CONTINUE
CALL ADDREF ;YES, ADD REFERENCE
JMP LAL0 ;DONE
LAL2: CALL ENTSYM ;ENTER SYMBOL DEFINITION
CALL ADDREF ;ADD REFERENCE
JMP LAL0 ;CONTINUE
LAL3: CALL GETSYM ;COLLECT IDENTIFIER
JMP LALC ;CONTINUE
LNUM: CALL GETBYT ;GET BYTE
CALL SAVBYT ;SAVE BYTE IN PRINTER BUFFER
CALL CHKNUM ;TEST FOR NUMERIC
JNC LNUM ;YES, CONTINUE
CALL CHKALP ;TEST FOR ALPHABETIC
JNC LNUM ;YES, CONTINUE
JMP MAIN2 ;CONTINUE WITH MAIN SCAN
LQUOT: CALL GETBYT ;GET A BYTE
CALL SAVBYT ;SAVE BYTE IN PRINTER BUFFER
CPI '''' ;SEE IF STRING QUOTE
JNZ LQUOT ;NO, KEEP LOOPING
CALL GETBYT ;GET NEXT BYTE
CALL SAVBYT ;SAVE BYTE
CPI '''' ;TEST FOR DOUBLES
JZ LQUOT ;YES, START SCAN AGAIN
JMP MAIN2 ;NO, CONTINUE IN MAIN SCAN
LSEMI: CALL GETBYT ;GET A BYTE
CALL SAVBYT ;SAVE BYTE
CPI 0DH ;WAIT FOR CR
JNZ LSEMI ;CONTINUE
JMP MAIN2 ;ENTER MAIN LOOP
LCR: CALL PRLINE ;PRINT LINE
LHLD LCNT ;GET LINE NUMBER
INX H ;BUMP LINE NUMBER
SHLD LCNT ;STORE
CALL SKIP ;SKIP 1ST 16 CHAR. OF NEXT LINE
JMP MAIN ;CONTINUE
LIGN EQU MAIN ;RE-ENTER MAIN LOOP
LLF EQU MAIN
LSPC EQU MAIN
LTAB EQU MAIN
LDOL EQU MAIN
LDEL EQU MAIN
;********************************;
; SUBROUTINES
;********************************;
;********************************;
; SKIP FIRST SIXTEEN
; CHARACTERS IN A LINE
;********************************;
SKIP: MVI B,16 ;SET COUNTER
SKIP1: PUSH B ;SAVE IT
SKIP2: CALL GETBYT ;GET BYTE
CALL SAVBYT ;SAVE IT IN PRINT BUFFER
CPI EOF ;EOF?
JZ DONE ;BRIF IS
CPI 0AH ;LF?
JZ SKIP2 ;BRIF IS, IE. DON'T COUNT
CPI 0DH ;CR?
JZ SKIP2 ;BRIF IS, IE. DON'T COUNT
POP B ;RETRIEVE COUNTER
DCR B ;DECREMENT
JNZ SKIP1
RET
;********************************;
; INITIALIZATION
;********************************;
SETUP: LXI D,TFCB ;POINT TO FCB
CALL FOPEN ;OPEN FCB
LXI D,EMSG2 ;POINT TO ERROR MESSAGE
JC FERR1 ;BRIF FILE NOT FOUND
LXI H,PBUF
SHLD LPNT ;SET PRINT POINTER
LXI H,00001
SHLD LCNT
LXI H,SYMT ;GET ADDRESS OF SYMBOL TABLE
SHLD SYM
SHLD SYMBT
SHLD SYMTP ;SET SYMBOL TABLE POINTERS
LHLD MEMSZ ;GET AVAILABLE MEMORY ADDRESS
DCX H
SHLD REF
SHLD REFBT
SHLD REFTP ;SET REFERENCE TABLE POINTERS
CALL PAGE ;ISSUE PAGE EJECT
RET
;********************************;
; CHECK FOR RESERVED WORD
;********************************;
CKRES: LXI H,RWTBL ;POINT TO RESERVED WORD TABLE
SHLD TEMP ;SAVE IN TEMP WORD
CKRES1: LHLD TEMP ;GET TABLE POINTER
LXI D,SBUF ;POINT TO SYMBOL
MVI B,RWSIZ ;RESERVED WORD SIZE
CKRES2: LDAX D ;GET SYMBOL BYTE
CMP M ;COMPARE AGAINST TABLE ENTRY
RC ;LESS, NOT IN TABLE
JNZ CKRES3 ;GREATER, GET NEXT TABLE ENTRY
INX D ;BUMP POINTERS
INX H
DCR B ;DECREMENT BYTE COUNT
JNZ CKRES2 ;KEEP TESTING
JMP CKRES4 ;FOUND
CKRES3: LHLD TEMP ;GET TABLE POINTER
LXI D,RWSIZ ;SIZE OF ENTRY
DAD D ;BUMP POINTER
SHLD TEMP ;STORE NEW POINTER
MOV A,M ;GET TABLE BYTE
CPI 0FFH ;END OF TABLE?
JNZ CKRES1 ;NO, LOOP
STC ;SET CARRY (NOT IN TABLE)
RET
CKRES4: ORA A ;RESET CARRY
RET
;********************************;
; FIND SYMBOL IN TABLE
;********************************;
FIND: LHLD SYMBT ;GET BEGIN OF SYM TABLE
SHLD SYM ;SET TEMP POINTER
FIND1: LHLD SYM ;GET TEMP POINTER
LXI D,SBUF ;POINT TO CURRENT SYMBOL
MVI B,SYMSZ ;SYMBOL 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 SYM ;GET CURRENT POINTER
LXI D,STESZ ;SYMBOL TABLE ENTRY SIZE
DAD D ;BUMP POINTER
XCHG ;INTO DE
LHLD SYMTP ;GET TOP OF SYMBOL TABLE
CALL CPHL ;TEST FOR END OF TABLE
JZ FIND4 ;YES, DONE
JC FERR ;TABLE OVERFLOW, ERROR
XCHG ;CURRENT POINTER INTO HL
SHLD SYM ;SET CURRENT POINTER
JMP FIND1 ;LOOP
FIND4: STC ;SET CARRY FOR NOT FOUND
LHLD SYMTP ;GET CURRENT TOP
SHLD SYM ;SET CURRENT POINTER
RET
FERR: LXI D,EMSG1 ;POINTER TO ERROR MESSAGE
FERR1: MVI C,PRBUF
CALL BDOS ;PRINT ERROR MESSAGE
JMP BOOT ;EXIT
;********************************;
; ADD REFERENCE TO REF TABLE
;********************************;
ADDREF: LHLD SYM ;GET SYMBOL POINTER
LXI D,SYMSZ ;OFFSET PAST SYMBOL
DAD D
MOV E,M
INX H
MOV D,M ;GET REFERENCE POINTER
LXI H,0000
CALL CPHL ;TEST FOR ZERO REF PTR
JZ BLDREF ;YES, BUILD REFERENCE ENTRY
LNK: 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 LNK ;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 NOS./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 ENTREF ;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
ENTREF: PUSH H ;SAVE REF SLOT ADDR
LHLD LCNT ;GET LINE NUMBER
XCHG ;INTO DE
POP H ;GET REF SLOT ADDR
MOV M,E
INX H
MOV M,D ;STORE LINE REF
RET ;DONE
;********************************;
; BUILD REF TABLE BLOCK
;********************************;
BLDREF: LHLD SYM ;GET SYMBOL POINTER
LXI D,SYMSZ ;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 ENTREF ;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 SYMTP ;GET SYMBOL TOP
CALL CPHL ;CHECK FOR BUMP
JZ FERR ;YES, NO ROOM
JNC FERR ;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 REF BLOCK
LHLD TEMP ;GET NEW REF BLOCK ADDR
SHLD REF ;STORE IN REF
MVI B,REFSZ ;SIZE OF REF BLOCK
MVI A,00
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 SYMBOL IN SYM TABLE
;********************************;
ENTSYM: LHLD SYM ;GET SYMBOL POINTER
XCHG ;INTO DE
LHLD SYMTP ;GET SYMBOL TABLE TOP
CALL CPHL ;CHECK FOR END OF TABLE
JZ NEWSYM ;YES, ADD SYMBOL AT END
LXI D,STESZ ;SYMBOL TABLE ENTRY SIZE
DAD D ;CALCULATE NEW END OF TABLE
XCHG ;INTO DE
LHLD REFBT ;REFERENCE TABLE BOTTOM
CALL CPHL ;TEST FOR TABLE OVERFLOW
JZ FERR ;FULL, ERROR
JC FERR ;YES, ERROR
LHLD SYMTP ;GET TABLE TOP
LXI D,STESZ-1 ;BUMP TO END OF ENTRY
DAD D
SHLD TO ;STORE IN TO ADDRESS
LXI D,STESZ
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 SYM ;GET CURRENT POINTER
SHLD LIMIT ;STORE AS LIMIT ADDRESS
CALL MOVUP ;MOVE TABLE UP IN MEMORY
NEWSYM: LHLD SYM ;GET CURRENT POINTER
LXI D,SBUF ;POINT TO SYMBOL
MVI B,SYMSZ ;SIZE OF SYMBOL
CALL MOVE ;COPY SYMBOL TO TABLE
MVI A,0
MOV M,A
INX H
MOV M,A ;SET POINTERS TO 0000
LHLD SYMTP ;GET SYMBOL TABLE TOP
LXI D,STESZ ;GET SYMBOL ENTRY SIZE
DAD D ;BUMP
SHLD SYMTP ;STORE NEW TOP
RET
;********************************;
; MOVE SYMBOL TABLE UP
;********************************;
MOVUP: 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
MOVUP2: 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 MOVUP2 ;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
;********************************;
; TEST FOR ALPHABETIC CHAR.
;********************************;
CHKALP: CPI 'A' ;ASCII 'A'
RC ;NO, EXIT
CPI 'Z'+1
CMC
RET
;********************************;
; TEST FOR NUMERIC CHAR
;********************************;
CHKNUM: CPI '0'
RC
CPI '9'+1
CMC
RET
;********************************;
; LOOK UP CHAR 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
;********************************;
; SAVE BYTE IN LINE BUFFER
;********************************;
SAVBYT: STA CHAR ;SAVE CHAR IN CHAR
LHLD LPNT ;GET LINE POINTER
MOV M,A ;SAVE BYTE
INX H ;BUMP POINTER
SHLD LPNT ;SAVE POINTER
RET
;********************************;
; PRINT SOURCE LINE WITH NUMBER
;********************************;
PRLINE: LHLD LCNT ;GET LINE NUMBER
CALL DECOT ;CONVERT TO DECIMAL
LXI H,DEC ;POINT TO DEC STRING
PL2: MOV E,M ;GET STRING BYTE
MOV A,E
CPI 0DH ;DONE?
JZ PL3 ;YES
CALL PRBYT ;PRINT BYTE
INX H ;BUMP POINTER
JMP PL2
PL3: MVI E,':'
CALL PRBYT ;PRINT ':'
MVI E,' '
CALL PRBYT ;PRINT ' '
CALL PRBYT ;PRINT SPACE
LXI H,PBUF ;POINT TO PRINT BUFFER
PL4: MVI A,00
STA COL ;SET COLUMN COUNT
PL41: MOV E,M ;GET BYTE
MOV A,E
CPI 0DH ;DONE?
JZ PL5
CPI 0AH ;LF?
JZ PL4A ;YES, IGNORE
CPI 09H ;TAB?
JNZ PL42 ;NO, CONTINUE
PUSH H ;SAVE HL
PL43: MVI E,' '
CALL PRBYT ;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 PRBYT ;PRINT BYTE
PL4A: INX H
JMP PL41
PL5: CALL CRLF ;PRINT CR,LF
LXI H,PBUF
SHLD LPNT ;RESET LINE POINTER
RET
;********************************;
; COLLECT SYMBOL IN SYM BUF
;********************************;
GETSYM: MOV B,A ;SAVE CHAR
LDA SYMCT ;GET SYMBOL COUNT
CPI SYMSZ ;MAX?
RNC ;YES, DONE
INR A
STA SYMCT
LHLD SYMPT
MOV M,B
INX H ;BUMP SYMBOL POINTER
SHLD SYMPT
RET
;********************************;
; PRINTER INTERFACES
;********************************;
;********************************;
; PRINT A SINGLE BYTE
;********************************;
PRBYT: PUSH B
MOV C,E ;SHIFT CHARACTER
CALL LIST ;PRINT IT
POP B
RET
;*********************************;
; ISSUE PAGE EJECT
;*********************************;
PAGE: MVI C,0CH
CALL LIST
XRA A
STA LINES ;SET LINE COUNT
RET
;********************************;
; ISSUE CR, LF & TEST PAGE
; ALSO TEST CONSOLE STATUS
;********************************;
CRLF: MVI C,0DH
CALL LIST
MVI C,0AH
CALL LIST
CALL CONST ;GET CONSOLE STATUS
ORA A ;TEST IT
JZ CRLF1 ;BRIF NO ENTRY
CALL CONIN ;ELSE GET CHARACTER
CPI 19 ;CONTROL-S?
JNZ BOOT ;BRIF NOT
CALL CONIN ;ELSE WAIT TO RESUME
CRLF1: LDA LINES
INR A
STA LINES ;INCREMENT LINE COUNT
CPI 60 ;TEST LINE COUNT
CZ PAGE ;IF 56 THEN NEW PAGE
RET
;********************************;
; CHARACTER PARSING TABLE
;********************************;
CPTBL: DB 0DH
DW LCR
DB 0AH
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 LDEL
DB '/'
DW LDEL
DB ','
DW LDEL
DB ':'
DW LDEL
DB EOF
DW DONE
DB 0FFH
DW 0000H
EOF EQU 1AH ;EOF CODE
;********************************;
; RESERVED WORD TABLE
;********************************;
RWTBL: DB 'A '
DB 'ACI '
DB 'ADC '
DB 'ADD '
DB 'ADI '
DB 'ANA '
DB 'AND '
DB 'ANI '
DB 'B '
DB 'C '
DB 'CALL '
DB 'CC '
DB 'CM '
DB 'CMA '
DB 'CMC '
DB 'CMP '
DB 'CNC '
DB 'CNZ '
DB 'CP '
DB 'CPE '
DB 'CPI '
DB 'CPO '
DB 'CZ '
DB 'D '
DB 'DAA '
DB 'DAD '
DB 'DB '
DB 'DCR '
DB 'DCX '
DB 'DI '
DB 'DS '
DB 'DW '
DB 'E '
DB 'EI '
DB 'END '
DB 'ENDIF '
DB 'ENDM '
DB 'EQU '
DB 'H '
DB 'HLT '
DB 'IF '
DB 'IN '
DB 'INR '
DB 'INX '
DB 'JC '
DB 'JM '
DB 'JMP '
DB 'JNC '
DB 'JNZ '
DB 'JP '
DB 'JPE '
DB 'JPO '
DB 'JZ '
DB 'L '
DB 'LDA '
DB 'LDAX '
DB 'LHLD '
DB 'LXI '
DB 'M '
DB 'MACRO '
DB 'MOD '
DB 'MOV '
DB 'MVI '
DB 'NOP '
DB 'NOT '
DB 'OR '
DB 'ORA '
DB 'ORG '
DB 'ORI '
DB 'OUT '
DB 'PCHL '
DB 'POP '
DB 'PSW '
DB 'PUSH '
DB 'RAL '
DB 'RAR '
DB 'RC '
DB 'RET '
DB 'RLC '
DB 'RM '
DB 'RNC '
DB 'RNZ '
DB 'RP '
DB 'RPE '
DB 'RPO '
DB 'RRC '
DB 'RST '
DB 'RZ '
DB 'SBB '
DB 'SBI '
DB 'SET '
DB 'SHL '
DB 'SHLD '
DB 'SHR '
DB 'SP '
DB 'SPHL '
DB 'STA '
DB 'STAX '
DB 'STC '
DB 'SUB '
DB 'SUI '
DB 'TITLE '
DB 'XCHG '
DB 'XOR '
DB 'XRA '
DB 'XRI '
DB 'XTHL '
DB 0FFH ;END OF RESERVED WORD TABLE
RWSIZ EQU 6 ;SIZE OF TABLE ENTRY
;********************************;
; OPERATING SYSTEM EQUATES
;********************************;
BOOT EQU 0 ;REBOOT CP/M ENTRY POINT
BDOS EQU 0005H ;BDOS ENTRY POINT
MEMSZ EQU 0006H ;END OF MEMORY POINTER
TBSZE EQU 20H ;TRANS. BUFFER SIZE IN SECTORS
TFCB EQU 005CH ;TRANS. FCB
PRBUF EQU 9 ;PRINT BUFFER
OPEN EQU 15 ;OPEN FUNCTION CODE
STDMA EQU 26 ;SET DMA FUNCTION CODE
READ EQU 20 ;READ FUNCTION CODE
;********************************;
; F O P E N ;
; ROUTINE TO OPEN A DISK FILE ;
; INPUT: DE=A(FCB) ;
; OUTPUT: CARRY=ERROR ;
;********************************;
FOPEN: MVI C,OPEN ;OPEN CODE
CALL BDOS ;ISSUE OPEN
CPI 0FFH ;ERROR?
JZ FOERR ;YES
XRA A ;CLEAR CARRY
RET
FOERR: STC
RET
;********************************;
; G E T B Y T ;
; ROUTINE TO READ A BYTE ;
; OUTPUTS: A=BYTE ;
; CARRY=ERROR ;
;********************************;
GETBYT: LHLD TBDMA ;GET END OF BUFFER
XCHG ;TO DE
LHLD INPTR ;CURRENT POINTER IN HL
CALL CPHL ;TEST FOR END OF BUFFER
JZ GETB2 ;YES, READ
GETB1: MOV A,M ;GET BYTE
INX H ;BUMP POINTER
SHLD INPTR ;SAVE POINTER
ORA A ;RESET CARRY
RET
GETB2: LDA TBFLG ;GET FLAG
ORA A ;TEST IT
JNZ IERR ;BRIF NO MORE
LXI H,TBUF-128 ;ELSE SET START OF BUFFER
MVI A,TBSZE ;AND BUFFER SIZE IN SECTORS
GETB3: STA TBCNT ;SAVE IT
LXI D,128 ;CALCULATE NEW STARTING
DAD D ;ADDRESS
SHLD TBDMA ;SAVE IT
XCHG ;PLACE IT IN DE
MVI C,STDMA ;SET DMA ADDRESS
CALL BDOS
MVI C,READ ;READ CODE
LXI D,TFCB ;FCB ADDRESS
CALL BDOS ;ISSUE READ
ORA A ;CHECK FOR ERROR/E-O-F
JNZ GETB4 ;BRIF IS
LHLD TBDMA ;ELSE GET LAST DMA STARTING ADDR
LDA TBCNT ;GET SECTOR COUNT
DCR A ;SUBTRACT ONE
JNZ GETB3 ;BRIF SOME MORE
LXI D,128 ;ELSE SET NEW END OF BUFFER
DAD D
SHLD TBDMA
JMP GETB5
GETB4: MVI A,0FFH ;SET FLAG
STA TBFLG
GETB5: LXI H,TBUF ;RESET BUFFER POINTER
JMP GETB1 ;CONTINUE
IERR: STC
RET
;********************************;
; MISCELLANEOUS SUBROUTINES ;
;********************************;
;********************************;
; BIOS VECTORS ;
;*******************************;
CONST: JMP $-$ ;CONSOLE STATUS
CONIN: JMP $-$ ;CONSOLE INPUT
LIST: JMP $-$ ;LIST OUTPUT
;********************************;
; C P H L ;
; ROUTINE TO COMPARE HL VS DE ;
;********************************;
CPHL: MOV A,H
CMP D
RNZ
MOV A,L
CMP E
RET
;********************************;
; D A T A ;
;********************************;
XRFHD: DB 'CROSS REFERENCE:'
EMSG1: DB 'SYMBOL TABLE ERROR',0DH,0AH,'$'
EMSG2: DB 'NO SUCH FILE',0DH,0AH,'$'
SYMSZ EQU 7 ;SYMBOL SIZE
STESZ EQU SYMSZ+2 ;SYMBOL TABLE ENTRY SIZE
REFSZ EQU 2+(12*2) ;NUMBER OF BYTES IN REF BLOCK
DEC: DS 5
DB 0DH
LINES: DB 0 ;PRINT LINE COUNT
INPTR: DW TBUF+(TBSZE*128) ;INPUT BUFFER
TBDMA: DW TBUF+(TBSZE*128) ;DMA/E-O-B ADDRESS
TBFLG: DB 0 ;TRANS. BUFFER FLAG
;00 = SOME MORE
;FF = NO MORE
SYMBT: DS 2 ;SYMBOL TABLE BOTTOM ADDRESS
SYMTP: DS 2 ;SYMBOL TABLE TOP ADDRESS
REFBT: DS 2 ;REFERENCE TABLE BOTTOM ADDRESS
REFTP: DS 2 ;REFERENCE TABLE TOP ADDRESS
SYM: DS 2 ;CURRENT SYMBOL TABLE ADDRESS
REF: DS 2 ;CURRENT REFERENCE TABLE ADDRESS
FROM: DS 2 ;MOVE POINTER
TO: DS 2 ;TO POINTER
LIMIT: DS 2 ;LIMIT POINTER
COL: DS 1
CHAR: DS 1
LCNT: DS 2 ;LINE COUNTER
LPNT: DS 2
PBUF: DS 132
SYMCT: DS 1
SYMPT: DS 2
SBUF: DS SYMSZ
TEMP: DS 2 ;TEMP SAVE WORD
TBCNT: DS 1 ;TRANS. BUFFER SECTOR COUNT
TBUF: DS TBSZE*128 ;TRANS. BUFFER
DS 64
STACK EQU $ ;TOP OF STACK
;***********************************;
; SYMBOL TABLE AREA
; THE SYMBOL TABLE MUST BE
; THE LAST BYTE OF THE PROGRAM
;***********************************;
SYMT: ORG $
END