;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