; ; THIS IS THE PROCESSOR TECHNOLOGY SELF CONTAINED SYSTEM ; (ALSO CALLED SOFTWARE PACKAGE NO. 1) ; ; THIS ROUTINE INITILALIZES THE FILE AREA FOR SUBSEQUENT PROCESSING ; ORG 100H INITA: MVI A,3 OUT 20Q MVI A,21Q OUT 20Q ;SET UP ACIA LXI H,FILE0 MVI C,MAXFIL*FELEN XRA A INIT2: MOV M,A INX H DCR C JNZ INIT2 ; ; THIS IS THE STARTING POINT OF THE SELF CONTAINED SYSTEM ONCE ; THE SYSTEM HAS BEEN INITIALIZED. COMMANDS ARE READ FROM THE USER, ; EXECUTED, AND CONTROL RETURNS BACK TO THIS POINT TO READ ANOTHER ; USER COMMAND. ; SYS8: LXI SP,AREA+18 CALL READ ;READ INPUT LINE INX H MOV A,M ;FETCH FIRST CHARACTER CPI '9'+1 ;COMMAND OR LINE NUMBER JC LINE ;JUMP IF LINE FOR FILE CALL VALC ;GET COMMAND VALUES CALL COMM ;CHECK LEGAL COMMANDS EOR: CALL CRLF ;GET HERE WHEN ROUTINE IS DONE JMP SYS8 ; ; ; THIS ROUTINE READS IN A LINE FROM THE TTY AND PLACES IT IN AN ; INPUT BUFFER ; THE FOLLOWING ARE SPECIAL CHARACTERS ; CR - TERMINATES READ ROUTINE ; LF - NOT RECOGNIZED BY ROUTINE ; CONTROL X - DELETE CURRENT LINE ; DEL - DELETE CHARACTER ; ALL DISPLAYABLE CHARACTERS BETWEEN BLANK-Z AND THE ABOVE ; ARE RECOGNIZED BY THE READ ROUTINE. ALL OTHERS ARE SKIPPED ; THE ROUTINE WILL NOT ACCEPT MORE CHARACTERS THAN THE INPUT ; BUFFER WILL HOLD. ; READ: LXI H,IBUF ;SET INPUT BUFFER ADDRESS SHLD ADDS ;SAVE ADDRESS MVI E,2 ;INITIALIZE CHAR COUNT NEXT: CALL IN8 ;READ A LINE MOV A,B CPI 24 ;CHECK FOR CONTROL X JNZ CR CALL CRLF ;OUTPUT A CRLF JMP READ CR: CPI ASCR ;GET AN ASCII CR JNZ DEL MOV A,L CPI IBUF AND 0FFH JZ READ MVI M,ASCR ;PLACE CR AT END OF LINE INX H MVI M,1 ;PLACE OEF INDICATOR IN LINE INX H MVI A,IBUF+83 CALL CLER ;CLEAR REMAINING BUFFER LXI H,IBUF-1 MOV M,E ;SAVE CHAR COUNT RET DEL: CPI 127 ;CHECK FOR DELETE CHAR JNZ CHAR MVI A,IBUF CMP L ;IS THIS FIRST CHAR JZ NEXT DCX H ;DECR POINTER DCR E ;DECR COUNT BSPA: MVI B,5FH CALL OUT8 JMP NEXT CHAR: CPI ' ' ;CHECK FOR LEGAL CHAR JC NEXT CPI 'Z'+1 JNC NEXT MOV B,A CALL OUT8 ;ECHO CHAR MOV M,A MVI A,IBUF+81 CMP L ;CHECK FOR END OF LINE JZ BSPA INX H INR E ;INCR CHAR COUNT JMP NEXT ; ; ; THIS ROUTINE IS USED TO BLANK OUT A PORTION OF MEMORY ; CLER: CMP L RZ MVI M,' ' INX H JMP CLER ; ; THIS ROUTINE IS USED TO READ BYTE OF DATA FROM THE UART ; IN8: IN 20Q ;GET STATUS RRC ;MOVE INTO CARRY JNC IN8 IN 21Q ;GET THE DATA ANI 7FH ;MASK OFF PARITY BIT MOV B,A RET ; ; THIS ROUTINE OUTPUTS A BYTE OF DATA TO THE UART ; OUT8: IN 20Q ;GET STATUS RRC RRC JNC OUT8 OK: MOV A,B OUT 21Q ;SEND OUT THE DATA RET ; ; THIS ROUTINE WILL OUTPUT A CARRIAGE RETURN AND LINE FEED ; FOLLOWED BY TWO DELETE CHARACTERS WHICH PROVIDE TIME FOR A ; PRINT HEAD TO RETURN ; CRLF: MVI B,13 ;CR CALL OUT8 LF: MVI B,10 ;LF CALL OUT8 MVI B,127 CALL OUT8 CALL OUT8 RET ; ; THIS ROUTINE JUMPS TO A LOCATION IN MEMORY GIVEN BY THE ; INPUT COMMAND ; EXEC: CALL VCHK ;CHECK FOR PARAMETER CALL CRLF LHLD BBUF ;FETCH ADDRESS PCHL ;JUMP TO PROGRAM ; ; THIS ROUTINES CHECKS THE INPUT COMMAND AGAINST ALL LEGAL COMMANDS ; STORED IN A TABLE. IF A LEGAL COMMAND IS FOUND A JUMP IS ; MADE TO THAT ROUTINE; OTHERWISE AN ERROR MESSAGE IS OUTPUT ; TO THE USER ; COMM: LXI D,CTAB ;COMMAND TABLE ADDRESS MVI B,NCOM ;NUMBER OF COMMANDS MVI A,4 ;LENGTH OF COMMAND STA NCHR ;SAVE CALL COMS ;SEARCH TABLE JNZ WHAT ;JUMP IF ILLEGAL COMMAND PCHL ;JUMP TO ROUTINE ; ; THIS ROUTINE CHECKS IF A BASE CHARACTER STRING IS EQUAL TO ; ANY OF THE STRINGS CONTAINED IN A TABLE POINTED TO BY ; D,E. THE LENGTH OF THE STRINGS ARE <256. ON RETURN IF THE ; ZERO FLAG IS SET A MATCH WAS FOUND; IF THE ZERO FLAG IS CLEAR, ; NO MATCH WAS FOUND. REGISTER B CONTAINS THE NUMBER OF ; STRINGS TO COMPARE. ; THE TABLE CONSISTS OF ANY NUMBER OF CHARS, WITH 2 BYTES CONTAINING ; VALUES ASSOCIATED WITH IT. IT CAN BE USED TO SEARCH THROUGH ; A COMMAND TABLE OR SYMBOL TABLE. ; ON RETURN D,E POINT TO THE LAST BYTE ASSOCIATED WITH THE CHARACTER ; STRING IF A MATCH WAS FOUND. IF NO MATCH WAS FOUND, D,E POINT TO ; THE NEXT LOCATION AFTER THE END OF THE TABLE. ; COMS: LHLD ADDS ;FETCH COMPARE ADDRESS LDA NCHR ;GET LENGTH OF STRING MOV C,A CALL SEAR ;COMPARE STRINGS LDAX D MOV L,A INX D LDAX D ;FETCH VALUE MOV H,A RZ INX D ;SET TO NEXT STRING DCR B ;DECR COUNT JNZ COMS INR B ;CLEAR ZERO FLAG RET ; ; THIS ROUTINE CHECKS IF TWO CHARACTER STRINGS CONTAINED IN MEMORY ; ARE EQUAL. THE STRINGS ARE POINTED TO BY H,L AND D,E. ; ON RETURN, THE ZERO FLAG SET INDICATES A MATCH. REGISTER C ; INDICATES THE LENGTH OF THE STRINGS. ON RETURN, THE POINTERS ; POINT TO THE NEXT ADDRESS AFTER THE CHARACTER STRINGS ; SEAR: LDAX D ;FETCH CHAR CMP M ;COMPARE STRINGS JNZ INCA INX H INX D DCR C ;DECR CHAR COUNT JNZ SEAR RET INCA: INX D DCR C JNZ INCA INR C ;CLEAR ZERO FLAG RET ; ; THIS ROUTINE ZEROS OUT A BUFFER IN MEMORY WHICH IS THEN ; USED BY OTHER SCANNING ROUTINES ; ZBUF: XRA A ;GET A ZERO LXI D,ABUF+12 ;BUFFER ADDRESS MVI B,12 ;BUFFER LENGTH ZBU1: DCX D ;DECR ADDR STAX D ;ZERO BUFFER DCR B JNZ ZBU1 RET ; ; THIS ROUTINE CALLS ETRA TO OBTAIN THE INPUT PARAMETER VALUES ; AND CALLS AN ERROR ROUTINE IF AN ERROR OCCURS ; VALC: CALL ETRA ;GET INPUT PARAMETERS JC WHAT ;JUMP IF ERROR RET ; ; THIS ROUTINE EXTRACTS THE VALUES ASSOCIATED WITH A COMMAND ; FROM THE INPUT STREAM AND PLACES THEM IN THE ASCII BUFFER (ABUF) ; IT ALSO CALLS A ROUTINE TO CONVERT THE ASCII HEXADECIMAL TO BINARY ; AND STORES THEM IN THE BINARY BUFFER (BBUF) ; ON RETURN, CARRY SET INDICATES AN ERROR IN INPUT PARAMETERS ; ETRA: LXI H,0 ;GET A ZERO SHLD BBUF+2 ;ZERO VALUE SHLD FBUF ;SET NO FILE NAME CALL ZBUF ;ZERO BUFFER LXI H,IBUF-1 ;INPUT BUFFER ADDRESS VAL1: INX H MOV A,M ;FETCH INPUT CHAR CPI ' ' ;LOOK FOR FIRST BLANK CMC RNC JNZ VAL1 ;JUMP IF NO BLANK SHLD PNTR ;SAVE POINTER CALL SBLK ;SCAN TO FIRST PARAMETER CMC RNC ;RETURN IF CR CPI '/' JNZ VAL5 ;NO FILE NAME LXI D,FBUF ;NAME FOLLOWS PUT IN FBUF MVI C,NMLEN VAL2: INX H MOV A,M CPI '/' JZ VAL3 DCR C JM WHAT STAX D ;STORE FILE NAME NOP INX D JMP VAL2 VAL3: MVI A,' ' ;GET AN ASCII SPACE VAL4: DCR C JM DONE STAX D ;FILL IN WITH SPACES INX D JMP VAL4 DONE: CALL SBL2 CMC RNC VAL5: LXI D,ABUF CALL ALPS ;PLACE PARAMETER IN BUFFER MOV A,B ;GET DIGIT COUNT CPI 5 ;CHECK NUMBER OF DIGITS CMC RC ;RETURN IF TOO MANY DIGITS LXI B,ABUF CALL AHEX ;CONVERT VALUE RC ;ILLEGAL CHAR SHLD BBUF ;SAVE IN BINARY BUFFER LXI H,ABUF CALL NORM ;NORMALIZE ASCII VALUE CALL SBLK ;SCAN TO NEXT PARAMETER CMC RNC ;RETURN IF CR LXI D,ABUF+4 CALL ALPS ;PLACR PARAMETER IN BUFFER MOV A,B CPI 5 ;CHECK NUMBER OF DIGITS CMC RC ;RETURN IF TOO MANY DIGITS LXI B,ABUF+4 CALL AHEX ;CONVERT VALUE RC ;ILLEGAL CHAR SHLD BBUF+2 ;SAVE IN BINARY BUFFER LXI H,ABUF+4 CALL NORM ;NORMALIZE ASCII VALUE ORA A ;CLEAR CARRY RET ; ; THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED BY ; REGISTERS B,C AND CONVERST THE ASCII DECIMAL DIGITS INTO ; BINARY. UP TO A 16 BIT VALUE CAN BE CONVERTED. THE SCAN ; STOPS WHEN A BINARY ZERO IS FOUND IN THE BUFFER ; ADEC: LXI H,0 ;GET A 16 BIT ZERO ADE1: LDAX B ;FETCH ASCII DIGIT ORA A ;SET ZERO FLAG RZ ;RETURN IF FINISHED MOV D,H ;SAVE CURRENT VALUE MOV E,L ;SAVE CURRENT VALUE DAD H ;TIMES TWO DAD H ;TIMES TWO DAD D ;ADD IN ORIGINAL VALUE DAD H ;TIMES TWO SUI '0' ;ASCII BIAS CPI 10 ;CHECK FOR LEGAL VALUE CMC RC ;RETURN IF ERROR MOV E,A MVI D,0 DAD D ;ADD IN NEXT DIGIT INX B ;INCREMENT POINTER JMP ADE1 ; ; THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED BY ; REGISTERS B,C AND CONVERTS THE ASCII HEXADECIMAL DIGITS INTO ; BINARY. UP TO A 16 BIT VALUE CAN BE CONVERTED. THE SCAN STOPS ; WHEN A BINARY ZERO IS FOUND IN THE BUFFER ; AHEX: LXI H,0 ;GET A 16 BIT ZERO AHE1: LDAX B ;FETCH ASCII DIGIT ORA A RZ ;RETURN IF ZERO DAD H ;LEFT SHIFT DAD H DAD H DAD H CALL AHS1 ;CONVERT TO BINARY CPI 10H ;CHECK FOR LEGAL VALUE CMC RC ;RETURN IF ERROR ADD L MOV L,A INX B ;INCR POINTER JMP AHE1 ; ; THIS ROUTINE CONVERTS ASCII HEX DIGITS INTO BINARY ; AHS1: SUI '0' ;ASCII BIAS CPI 10 ;DIGIT 0-10 RC SUI 7 ;ALPHA BIAS RET ; ; THIS ROUTINE CONVERTS A BINARY VALUE TO ASCII HEXADECIMAL ; AND OUTPUTS THE CHARACTERS TO THE TTY ; HOUT: CALL BINH ;CONVERT VALUE LXI H,HCON ;CONVERSION AREA CHOT: MOV B,M ;FETCH OUTPUT CHARACTER CALL OUT8 ;OUTPUT CHAR INX H MOV B,M ;FETCH CHAR CALL OUT8 ;OUTPUT CHAR RET ; ; THIS ROUTINE DOES THE SAME AS ABOVE BUT OUTPUTS A BLANK ; AFTER THE LAST CHAR ; HOTB: CALL HOUT ;CONVERT AND OUTPUT CALL BLK1 ;OUTPUT A BLANK RET ; ; THIS ROUTINE CONVERTS A BINARY VALUE TO ASCII DECIMAL ; DIGITS AND OUTPUTS THE CHARACTERS TO THE TTY ; DOUT: CALL BIND ;CONVERT VALUE CALL HOUT+3 ;OUTPUT VALUE (2 DIGITS) INX H MOV B,M ;GET LAST DIGIT CALL OUT8 ;OUTPUT RET ; ; THIS ROUTINE OUTPUTS A BLANK ; BLK1: MVI B,' ' CALL OUT8 RET ; ; THIS ROUTINE IS USED BY OTHER ROUTINES TO INCREMENT THE ; STARTING ADDRESS IN A COMMAND AND COMPARE IT WITH THE FINAL ; ADDRESS IN THE COMMAND. ON RETURN THE CARRY FLAG SET ; INDICATES THAT THE FINAL ADDRESS HAS BEEN REACHED ; ACHK: LHLD BBUF ;FETCH START ADDRESS LDA BBUF+3 ;STOP ADDRESS (HIGH) CMP H ;COMPARE JNZ ACH1 LDA BBUF+2 ;STOP ADDRESS (LOW) CMP L ;COMPARE JNZ ACH1 STC ;SET CARRY IF EQUAL ACH1: INX H ;INCREMENT START ADDRESS SHLD BBUF ;STORE START ADDRESS RET ; ; THIS ROUTINE OUTPUTS CHARACTERS FROM A CHARACTER STRING UNTIL ; A CARRIAGE RETURN IS FOUND ; SCRN: MOV B,M ;FETCH CHAR MVI A,13 ;CARRIAGE RETURN CMP B ;CHAR = CR RZ CALL OUT8 ;OUTPUT CHAR INX H ;INCREMENT ADDRESS JMP SCRN ; ; THIS ROUTINE CONVERTS THE BINARY VALUE IN REG A INTO ; ASCII HEXADECIMAL DIGITS AND STORES THEM IN MEMORY ; BINH: LXI H,HCON ;CONVERSION ADDRESS MOV B,A ;SAVE VALUE RAR RAR RAR RAR CALL BIN1 MOV M,A INX H MOV A,B CALL BIN1 ;CONVERT TO ASCII MOV M,A RET ; ; THIS ROUTINE CONVERTS A VALUE TO HEXADECIMAL ; BIN1: ANI 0FH ;LOW FOUR DIGITS ADI '0' ;MODIFY FOR ASCII CPI '0'+10 ;DIGIT 0-9 RC ADI 7 ;MODIFY FOR A-F RET ; ; THIS ROUTINE CONVERTS THE BINARY VALUE IN THE A REG ; TO ASCII DECIMAL DIGITS AND STORES THEM IN MEMORY ; BIND: LXI H,HCON ;CONVERSION ADDRESS MVI B,100 CALL BID1 ;CONVERT HUNDREDS DIGIT MVI B,10 CALL BID1 ;CONVERT TENS DIGIT ADI '0' ;GET UNITS DIGIT MOV M,A ;STORE IN MEMORY RET ; ; THIS ROUTINE CONVERTS A VALUE TO DECIMAL ; BID1: MVI M,'0'-1 ;INITIALIZE DIGIT COUNT INR M SUB B ;CHECK DIGIT JNC BID1+2 ADD B ;RESTORE VALUE INX H RET ; ; LEGAL COMMAND TABLE ; CTAB: DB 'DUMP' ;DUMP COMMAND DW DUMP DB 'EXEC' DW EXEC DB 'ENTR' DW ENTR DB 'FILE' DW FILE DB 'LIST' DW LIST DB 'DELT' DW DELL DB 'ASSM' DW ASSM DB 'PAGE' DW PAGE DB 'PROM' DW PROM DB 'CUST' DW 0E000H ; ; THIS ROUTINE CHECKS IF ANY PARAMETERS WERE ENTERED ; WITH THE COMMAND; IF NOT, AN ERROR MESSAGE IS ISSUED ; VCHK: LDA ABUF ;FETCH PARAMETER BYTE ORA A ;SET FLAGS JZ WHAT ;NO PARAMETER RET ; ; THIS ROUTINE DUMPS THE CONTENTS OF MEMORY FROM ; THE START TO FINAL ADDRESSES GIVEN IN THE COMMAND ; DUMP: CALL VCHK ;CHECK FOR PARAMETERS MVI A,16 ;LOCATIONS PER LINE STA SCNT ;DUMP COUNTER DUMS: CALL CRLF ;START NEW LINE LDA BBUF+1 ;FETCH ADDRESS CALL HOUT ;OUTPUT ADDRESS LDA BBUF CALL HOTB ;OUTPUT ADDRESS LDA SCNT ;FETCH LINE COUNTER DUM1: STA DCNT LHLD BBUF ;FETCH MEMORY ADDRESS MOV A,L ;GET LOW ORDER ADDRESS OUT PADO ;SET PROM ADDRESS MOV A,H CPI 0EFH MOV A,M JNZ DUM2 IN PDAI ;READ PROM DATA DUM2: CALL HOTB ;OUTPUT VALUE CALL ACHK ;CHECK ADDRESS RC ;RETURN IF FINISHED LDA DCNT ;FETCH COUNTER DCR A ;DECR COUNTER JNZ DUM1 JMP DUMS ; ; THIS ROUTINE WILL MOVE 1 PAGE (256 BYTES) FROM 1ST ADDRESS GIVEN ; IN COMMAND TO 2ND ADDRESS IN COMMAND ; PAGE: CALL VCHK ;CHECK FOR PARAMETER LDA ABUF+4 ;FETCH 2ND PARAMETER ORA A ;DOES 2ND PARAMETER EXIST? JZ WHAT LHLD BBUF ;FETCH MOVE FROM ADDRESS XCHG LHLD BBUF+2 ;FETCH MOVE TO ADDRESS MVI B,0 ;SET COUNTER PAG1: MOV A,E OUT PADO ;SET PROM ADDRESS MOV A,D CPI 0FFH ;CHECK FOR PROM ADDRESS LDAX D ;GET DATA JNZ PAG2 IN PDAI ;READ PROM DATA PAG2: MOV M,A INX H INX D DCR B ;DECR COUNT JNZ PAG1 RET ; ; THIS ROUTINE INITIALIZES THE BEGINNING OF FILE ADDRESS ; AND END OF FILE ADDRESS AS WELL AS THE FILE AREA ; WHEN THE FILE COMMAND IS USED ; FILE: CALL CRLF ;CHECK FOR FILE PARAMETERS LDA FBUF ORA A JZ FOUT ;NO GO LIST CALL FSEA ;LOOK UP FILE XCHG ;PNTR IN DE JNZ TEST ;IF FOUND ;NO ENTRY LDA ABUF ;CHECK FOR PARAM ORA A JZ WHA1 ;NO?? - GIVE EM HELL ;CHECK FOR ROOM IN DIRECTORY LDA FEF ORA A JNZ ROOM LXI H,EMES1 JMP MESS ;ENTRY FOUND ARE THESE PARAMETERS TEST: LDA ABUF ORA A JZ SWAPS LHLD BBUF MOV A,H ORA L JZ SWAPS LXI H,EMES2 ;NO-NO CAN'T DO JMP MESS ;MOVE FILE NAME TO BLOCK POINTED TO BY FREAD ROOM: LHLD FREAD XCHG ;DIRECT POINTER IN D,E LXI H,FBUF ;FILE NAME POINTER IN H,L PUSH D MVI C,NMLEN ;NAME LENGTH COUNT MOV23: MOV A,M STAX D INX D INX H DCR C ;TEST COUNT JNZ MOV23 POP D ;RESTORE ENTRY PTR, MAKE CURRENT ;MAKE FILE POINTED TO BY D,E CURRENT SWAPS: LXI H,FILE0 MVI C,FELEN ;ENTRY LENGTH SWAP: LDAX D MOV B,M MOV M,A MOV A,B STAX D INX D ;BUMP POINTERS INX H DCR C ;TEST COUNT JNZ SWAP ;CHECK FOR 2ND PARAMETER, => INITIALIZE NEW LDA ABUF ORA A JZ FOOT ;NO SECOND PARAMETER ;PROCESS SECOND PARAMETER LHLD BBUF ;GET ADDRESS SHLD BOFP ;SET BEGIN SHLD EOFP ;SET END MOV A,L ;IS ADDRESS ZERO? ORA H JZ FIL35 ;YES FIL30: MVI M,1 ;NON-ZERO - SET EOF FIL35: XRA A STA MAXL ;AND MAX LINE # JMP FOOT ;OUTPUT PARAMETERS FOUT: LDA IBUF+4 CPI 'S' ;IS COMMAND FILES MVI C,MAXFIL JZ FOUL FOOT: MVI C,1 ;OUTPUT THE # OF ENTRIES IN C FOUL: LXI H,FILE0 MOV A,C FINE: STA FOCNT ;SAVE COUNT PUSH H LXI D,NMLEN DAD D MOV A,M ORA A JNZ FOOD ;NON-ZERO, OK TO OUTPUT INX H ADD M INX H JNZ FOOD INX SP INX SP INX H INX H JMP FEET ;HAVE AN ENTRY TO OUTPUT FOOD: POP H ;PTR MVI C,NMLEN FAST: MOV B,M ;LOAD CHAR TO B CALL OUT8 ;OUTPUT DCR C INX H JNZ FAST ;DO THE REST ;NOW OUTPUT BEGIN-END PTRS CALL FOOL ;OUTPUT BEGIN CALL FOOL ;OUTPUT END CALL CRLF ;AND CR ;TEST COUNT, H,L POINTS PAST EOFP FEET: LXI D,FELEN-NMLEN-4 DAD D ;MOVE TO NEXT ENTRY LDA FOCNT DCR A ;TEST COUNT JNZ FINE ;MORE TO DO RET ;OUTPUT NUMBER POINTED TO BY H,L ;ON RET, H,L POINT 2 WORDS LATER FOOL: CALL BLK1 ;SPACE INX H MOV A,M DCX H PUSH H CALL HOUT ;OUTPUT POP H MOV A,M INX H INX H PUSH H CALL HOTB ;OUTPUT POP H ;RESTORE H,L RET ; ; SEARCH THE FILE DIRECTORY FOR THE FILE ; WHOSE NAME IS IN FBUF. ; RETURN IF FOUND, ZERO IS OFF, H,L POINT TO ; ENTRY WHILE SEARCHING. ON ENTRY FOUND WITH ADDR ; ZERO, SET FEF TO > 0 AND FREAD TO THE ADDR OF ENTRY ; FSEA: XRA A STA FEF ;CLAIM NO FREE ENTRIES MVI B,MAXFIL ;COUNT OF ENTRIES LXI D,FILE0 ;TABLE ADDRESS FSE10: LXI H,FBUF MVI C,NMLEN CALL SEAR ;TEST STRINGS PUSH PSW ;SAVE FLAG PUSH D LDAX D ;GET BOFP ORA A ;EMPTY ENTRY? JNZ FSE20 INX D ;TEST OTHER WORD LDAX D ORA A JNZ FSE20 ;NOPE-GO TEST FOR MATCH XCHG ;H,L GET MIDDLE OF FREE ENTRY LXI D,-NMLEN-1 DAD D ;MOVE TO BEGINNING SHLD FREAD ;SAVE ADDR MOV A,D STA FEF ;SET FREE ENTRY FOUND POP H ;RESTORE INTERIM POINTER POP PSW ;UNJUNK STACK ; MOVE TO NEXT ENTRY FSE15: LXI D,FELEN-NMLEN DAD D XCHG ;NEXT ENTRY ADDR IN DE DCR B ;TEST COUNT RZ ;DONE? JMP FSE10 ;TRY NEXT ; ENTRY WASN'T FREE, TEST FOR MATCH FSE20: POP H POP PSW JNZ FSE15 ;IF ZERO CLEAR, NO MATCH ; ENTRY FOUND LXI D,-NMLEN ;BACKUP DAD D ;H,L POINTS TO ENTRY MOV A,D ORA A ;CLEAR ZERO RET ;THAT'S ALL ; ; OUTPUT ERROR MESSAGE FOR ILLEGAL COMMAND ; WHAT: CALL CRLF ;OUTPUT CRLF WHA1: LXI H,EMES ;MESSAGE ADDRESS MESS: CALL SCRN JMP EOR ; EMES: DB 'WHAT?',13 EMES1: DB 'FULL',13 EMES2: DB 'NO NO',13 ; ; CALL ROUTINE TO ENTER DATA INTO MEMORY ; AND CHECK FOR ERROR ON RETURN ; ; THIS ROUTINE IS USED TO ENTER DATA VALUES INTO MEMORY. ; EACH VALUE IS ONE BYTE AND IS WRITTEN IN HEXADECIMAL ; VALUES GREATER THAN 255 WILL CAUSE CARRY TO BE SET ; AND RETURN MADE TO CALLING PROGRAM ; ENTR: CALL VCHK ;CHECK FOR PARAMETERS CALL ENTS JC WHAT CALL CRLF RET ; EEND EQU '/' ;TERMINATION CHAR ENTS: CALL CRLF CALL READ ;READ INPUT DATA LXI H,IBUF ;SET LINE POINTER SHLD PNTR ;SAVE POINTER ENT1: CALL ZBUF ;CLEAR BUFFER CALL SBLK ;SCAN TO FIRST VALUE JC ENTS ;JUMP IF CR FOUND CPI EEND RZ ;CARRY IS ZERO CALL ALPS ;PLACE VALUE IN BUFFER MOV A,B ;GET DIGIT COUNT CPI 3 ;CHECK NUMBER OF DIGITS CMC RC ;RETURN IF MORE THAN 2 DIGITS LXI B,ABUF ;CONVERSION ADDRESS CALL AHEX ;CONVERT VALUE RC ;ERROR IN HEX CHARACTER MOV A,L LHLD BBUF ;FETCH MEMORY ADDRESS MOV M,A ;PUT IN MEMORY CALL ACH1 ;INCREMENT MEMORY LOCATION JMP ENT1 ; ; THIS ROUTINE IS USED TO ENTER LINES INTO THE FILE ; AREA. THE LINE NUMBER IS FIRST CHECKED TO SEE IF IT IS ; A VALID NUMBER (0000-9999). NEXT IT IS CHECKED TO SEE IF IT IS ; GREATER THAN THE MAXIMUM CURRENT LINE NUMBER. IF IT IS, THE NEW ; LINE IS INSERTED AT THE END OF THE CURRENT FILE AND THE MAXIMUM ; LINE NUMBER IS UPDATED AS WELL AS THE END OF FILE POSITION ; LINE NUMBERS THAT ALREADY EXIST ARE INSERTED INTO THE FILE AREA ; AT THE APPROPRIATE PLACE AND ANY EXTRA CHARACTERS IN THE OLD ; LINE ARE DELETED ; LINE: MVI C,4 ;NO OF DIGITS TO CHECK LXI H,IBUF-1 ;INITIALIZE ADDRESS LICK: INX H MOV A,M ;FETCH LINE DIGIT CPI '0' ;CHECK FOR VALID NUMBER JC WHAT CPI '9'+1 JNC WHAT DCR C JNZ LICK SHLD ADDS ;FIND ADDRESS LXI D,MAXL+3 ;SET ADDRESS CALL COM0 JNC INSR ; GET HERE IF NEW LINE IS GREATER THAN MAXIMUM CURRENT LINE # INX H CALL LODM ;GET NEW LINE NUMBER LXI H,MAXL+3 CALL STOM ;MAKE IT MAXIMUM LINE NUMBER LXI D,IBUF-1 LHLD EOFP ;END OF FILE POSITION MVI C,1 CALL LMOV ;PLACE LINE IN FILE SEOF: MVI M,1 ;END OF FILE INDICATOR SHLD EOFP ;END OF FILE ADDRESS JMP EOR ; GET HERE IF NEW LINE MUST BE INSERTED INTO ALREADY EXISTING ; FILE AREA INSR: CALL FIN1 ;FIND LINE IN FILE MVI C,2 JZ EQUL DCR C ;NEW LN NOT EQUAL TO SOME OLD LINE EQUL: MOV B,M DCX H MVI M,2 ;MOVE LINE INDICATOR SHLD INSP ;INSERT LINE POSITION LDA IBUF-1 ;NEW LINE COUNT DCR C JZ LT ;NEW LINE NOT = OLD LINE SUB B ;COUNT DIFFERENCE JZ ZERO ;LINE LENGTHS EQUAL JC GT ; GET HERE IF NO OF CHARS IN OLD LINE > NO OF CHARS IN NEW LINE ; OR NEW LINE NUMBER WAS NOT EQUAL TO SOME OLD LINE NUMBER LT: LHLD EOFP ;END OF FILE ADDRESS MOV D,H MOV E,L CALL ADR ;MOVE TO ADDRESS SHLD EOFP ;NEW END OF FILE ADDRESS MVI C,2 CALL RMOV ;OPEN UP FILE AREA JMP ZERO ; GET HERE IF NO OF CHARS IN OLD LINE < NO OF CHARS IN NEW LINE GT: CMA INR A ;COUNT DIFFERENCE MOV D,H MOV E,L CALL ADR XCHG CALL LMOV ;DELETE EXCESS CHARS IN FILE MVI M,1 ;EOF INDICATOR SHLD EOFP ;EOF ADDRESS ; GET HERE TO INSERT CURRENT LINE INTO FILE AREA ZERO: LHLD INSP ;INSERT ADDRESS MVI M,ASCR INX H LXI D,IBUF-1 ;NEW LINE ADDRESS MVI C,1 ;CHECK VALUE CALL LMOV ;PLACE LINE IN FILE JMP EOR ; ; THIS ROUTINE IS USED TO FIND A LINE IN THE FILE AREA ; WHICH IS GREATER THAN OR EQUAL TO THE CURRENT LINE NUMBER ; FIND: LXI H,ABUF+3 ;BUFFER ADDRESS SHLD ADDS ;SAVE ADDRESS FIN1: LHLD BOFP ;BEGIN FILE ADDRESS FI1: CALL EO1 ;CHECK FOR END OF FILE XCHG LHLD ADDS ;FETCH FIND ADDRESS XCHG MVI A,4 CALL ADR ;LINE ADDRESS CALL COM0 ;COMPARE LINE NUMBER RC RZ FI2: MOV A,M CALL ADR ;NEXT LINE ADDRESS JMP FI1 ; ; THIS ROUTINE CHECKS IF THE CURRENT ADDRESS ; IS THE END OF FILE ; EOF: INX H EO1: MVI A,1 ;EOF INDICATOR CMP M RNZ JMP EOR ; ; THIS ROUTINE IS USED TO ADD A VALUE TO AN ADDRESS ; CONTAINED IN REGISTER H,L ; ADR: ADD L MOV L,A RNC INR H RET ; ; THIS ROUTINE WILL MOVE CHARACTER STRINGS FROM ONE LOCATION ; OF MEMORY TO ANOTHER ; CHARACTERS ARE MOVED FROM LOCATION ADDRESSED BY D,E TO LOCATION ; ADDRESSED BY H,L. ADDITIONAL CHARACTERS ARE MOVED BY ; INCREMENTING MEMORY UNTIL THE CHARACTER IN REGISTER C IS FETCHED ; LMOV: LDAX D ;FETCH CHAR INX D CMP C ;TERMINATION CHAR RZ MOV M,A INX H JMP LMOV ; ; THIS ROUTINE IS SIMILAR TO THE ABOVE EXCEPT THAT THE CHARACTER ; ADDRESS IS DECREMENTED AFTER EACH FETCH AND STORE ; RMOV: LDAX D ;FETCH CHAR DCX D CMP C ;TERMINATION CHAR RZ MOV M,A ;STORE CHAR DCX H ;DECR STORE ADDRESS JMP RMOV ; ; THIS ROUTINE IS USED TO LOAD FOUR CHARACTERS FROM ; MEMORY INTO REGISTERS ; LODM: MOV B,M ;FETCH CHAR INX H MOV C,M INX H MOV D,M INX H MOV E,M RET ; ; THIS ROUTINE STORES FOUR CHARACTERS FROM REGISTERS INTO MEMORY ; STOM: MOV M,E DCX H MOV M,D DCX H MOV M,C DCX H MOV M,B RET ; ; THIS ROUTINE IS USED TO COMPARE TWO CHARACTER STRINGS ; OF LENGTH 4. ON RETURN ZERO FLAG SET MEANS BOTH ; STRINGS ARE EQUAL. CARRY FLAG = 0 MEANS STRING ADDRESSED ; BY D,E WAS GREATER THAN OR EQUAL TO CHARACTER STRING ; ADDRESSED BY H,L ; COM0: MVI B,1 ;EQUAL COUNTER MVI C,4 ;STRING LENGTH ORA A ;CLEAR CARRY CO1: LDAX D ;FETCH CHARACTER SBB M ;COMPARE CHAR JZ CO2 INR B ;INCREMENT EQUAL COUNTER CO2: DCX D DCX H DCR C JNZ CO1 DCR B RET ; ; THIS ROUTINE IS SIMILAR TO THE ABOVE EXCEPT ON RETURN, CARRY = 0 ; MEANS THAT THE CHAR STRING ADDRESSED BY D,E IS STRICTLY GREATER ; THAN STRING ADDRESSED BY H,L ; COM1: MVI C,4 ;STRING LENGTH LDAX D ;FETCH CHAR SUI 1 JMP CO1+1 ; ; THIS ROUTINE WILL TAKE ASCII CHARS AND ADD ANY ; NECESSARY ASCII ZEROES SO THE RESULT IS A 4 CHARACTER ; ASCII VALUE ; NORM: CALL LODM ;LOAD ZEROES XRA A CMP B RZ NOR1: CMP E CNZ STOM ;STORE VALUES RNZ MOV E,D MOV D,C MOV C,B MVI B,'0' JMP NOR1 ; ; THIS ROUTINE IS USED TO LIST THE CONTENTS OF THE FILE ; AREA STARTING AT THE LINE NUMBER GIVEN IN THE COMMAND ; LIST: CALL CRLF CALL FIND ;FIND STARTING LINE INX H LIS1: CALL SCRN ;OUTPUT LINE CALL CRLF CALL EOF ;END OF FILE IN SWCH ;READ SWITCHES ANI 80H RNZ INX H JMP LIS1 ; ; THIS ROUTINE IS USED TO PROGRAM A 1702A PROM ; PROM: CALL VCHK ;CHECK FOR PARAMETER PRO1: CALL CRLF LDA BBUF ;GET ADDRESS (LOW) CALL HOTB ;OUTPUT ADDRESS MVI D,3 ;NUMBER OF ATTEMPTS LHLD BBUF ;GET ADDRESS PRO2: MOV A,L OUT PADO MOV A,M ;GET DATA OUT PDAO ;OUTPUT TO PROM MVI A,2 OUT PCTO ;ENABLE PROGRAMMER CALL DLAY ;500 MSEC DELAY XRA A OUT PCTO ;DISABLE PROGRAMMER IN PDAI ;READ DATA CMP M ;COMPARE DATA JZ PRO3 MVI B,'?' CALL OUT8 DCR D ;NUMBER OF ATTEMPTS JNZ PRO2 ;TRY AGAIN RET PRO3: CALL ACHK ;FINAL ADDRESS RC ;RETURN IF FINISHED JMP PRO1 ;NEXT LOCATION ; DLAY: MVI E,150 DLA1: XRA A ;GET A ZERO (256) DLA2: DCR A JNZ DLA2 DCR E JNZ DLA1 RET ; ; THIS ROUTINE IS UDED TO DELAETE LINES FROM THE FILE AREA ; THE REMAINING FILE AREA IS THEN MOVED IN MEMORY SO THAT ; THERE IS NO EXCESS SPACE IN MEMORY ; DELL: CALL VCHK ;CHECK FOR PARAMETER CALL FIND ;FIND LINE IN FILE AREA SHLD DELP ;SAVE DELETE POSITION LXI H,ABUF+7 MOV A,M ;CHECK FOR 2ND PARAMETER ORA A ;SET FLAGS JNZ DEL1 LXI H,ABUF+3 ;USE FIRST PARAMETER DEL1: SHLD ADDS ;SAVE FIND ADDRESS XCHG LXI H,MAXL+3 CALL COM0 ;COMPARE LINE NO LHLD DELP ;LOAD DELETE POSITION JC NOVR ; GET HERE IF DELETION INVOLVES END OF FILE SHLD EOFP ;CHANGE EOF POSITION MVI M,1 ;SET EOF INDICATOR XCHG LHLD BOFP ;GET BEGIN FILE ADDRESS XCHG MVI B,13 ;SET SCAN SWITCH DCX H ;DECREMENT FILE ADDRESS DEL2: MOV A,L ;CHECK FOR BOF SUB E MOV A,H SBB D MVI A,ASCR ;LOOK FOR CR JC DEL4 DCR B DCX H CMP M ;FIND NEW MAX LINE NO JNZ DEL2 DCX H MOV A,L SUB E MOV A,H SBB D JC DEL5 CMP M ;END OF PREVIOUS LINE INX H INX H JZ DEL3 INX H DEL3: CALL LODM ;LOAD NEW MAX LINE NO LXI H,MAXL+3 ;SET ADDRESS CALL STOM ;STORE NEW MAX LINE NO RET DEL4: CMP B ;CHECK SWITCH DEL5: XCHG JNZ DEL3-1 STA MAXL ;MAKE MAX LINE NO A SMALL NUMBER RET ; GET HERE IF DELETION IS IN MIDDLE OF FILE AREA NOVR: CALL FI1 ;FIND END OF FILE AREA CZ FI2 ;NEXT LINE IF THIS LINE NO IS EQUAL NOV1: XCHG LHLD DELP ;CHAR MOVE TO POSITION MVI C,1 ;MOVE TERMINATION CALL LMOV ;COMPACT FILE AREA SHLD EOFP ;SET EOF POSITION MVI M,1 ;SET EOF INDICATOR RET ; ; STARTING HERE IS THE SELF ASSEMBLER PROGRAM ; THIS PROGRAM ASSEMBLES PROGRAMS WHICH ARE ; IN THE FILE AREA ; ASSM: CALL VCHK ;CHECK FOR PARAMETER LDA ABUF+4 ;GET 2ND PARAMETER ORA A ;CHECK FOR PARAMETERS JNZ ASM4 LHLD BBUF ;FETCH 1ST PARAMETER SHLD BBUF+2 ;STORE INTO 2ND PARAMETER ASM4: LDA IBUF+4 ;FETCH INPUT CHAR CPI 'E' ;ERROR ONLY INDICATOR JNZ ASM5 XRA A ;SET FOR ONLY ERRORS ASM5: STA AERR ;SET ERROR SWITCH XRA A ;GET A ZERO STA NOLA ;INITIALIZE LABEL COUNT ASM3: STA PASI ;SET PASS INDICATOR LHLD BBUF ;FETCH ORIGIN SHLD ASPC ;INITIALIZE PC LHLD BOFP ;GET START OF FILE SHLD APNT ;SAVE ADDRESS ASM1: LHLD APNT ;FETCH LINE POINTER LXI SP,AREA+18 MOV A,M ;FETCH CHAR CPI 1 ;END OF FILE JZ EASS ;JUMP IF END OF FILE XCHG INX D ;INCREMENT ADDRESS LXI H,OBUF ;BLANK START ADDRESS MVI A,IBUF-5 ;BLANK END ADDRESS CALL CLER ;BLANK OUT BUFFER MVI C,ASCR ;STOP CHAR CALL LMOV ;MOVE LINE INTO BUFFER MOV M,C ;PLACE CR IN BUFFER XCHG SHLD APNT ;SAVE ADDRESS LDA PASI ;FETCH PASS INDICATOR ORA A ;SET FLAGS JNZ ASM2 ;JUMP IF PASS 2 CALL PAS1 JMP ASM1 ASM2: CALL PAS2 LXI H,OBUF ;OUTPUT BUFFER ADDRESS CALL AOUT ;OUTPUT LINE JMP ASM1 ; ; THIS ROUTINE IS USED TO OUTPUT THE LISTING FOR AN ASSEMBLY ; IT CHECKS WHETHER ALL LINES ARE PRINTED OR ONLY THOSE ; WITH ERRORS DEPENDING UPON THE ERROR SWITCH ; AOUT: LDA AERR ;FETCH ERROR SWITCH ORA A ;SET FLAGS JNZ AOU1 ;OUTPUT ALL LINES AOU2: LDA OBUF+18 ;FETCH ERROR INDICATOR CPI ' ' ;CHECK FOR AN ERROR RZ ;RETURN IF NO ERROR AOU1: LXI H,OBUF ;OUTPUT BUFFER ADDRESS CALL CRLF CALL SCRN ;OUTPUT LINE RET ; ; PASS 1 OF ASSEMBLER. USED TO FORM SYMBOL TABLE ; PAS1: CALL ZBUF ;CLEAR BUFFER STA PASI ;SET FOR PASS 1 LXI H,IBUF ;INITIALIZE LINE POINTER SHLD PNTR ;SAVE ADDRESS MOV A,M ;FETCH CHAR CPI ' ' ;CHECK FOR A BLANK JZ OPC ;JUMP IF NO LABEL CPI ';' ;CHECK FOR COMMENT RZ ;RETURN IF COMMENT ; ; PROCESS LABEL ; CALL SLAB ;GET AND CHECK LABEL JC OP5 ;ERROR IN LABEL JZ ERRD ;DUPLICATE LABEL CALL LCHK ;CHECK CHAR AFTER LABEL JNZ OP5 ;ERROR IF NO BLANK MVI C,LLAB ;LENGTH OF LABELS LXI H,ABUF ;SET BUFFER ADDRESS MLAB: MOV A,M ;FETCH NEXT CHAR STAX D ;STORE IN SYMBOL TABLE INX D INX H DCR C ;DECR COUNT JNZ MLAB XCHG SHLD TABA ;SAVE TABLE ADDRESS FOR EQU LDA ASPC ;FETCH PC (LOW) MOV M,A ;STORE IN TABLE INX H LDA ASPC+1 ;FETCH PC (HIGH) MOV M,A ;STORE IN TABLE LXI H,NOLA INR M ;INCR NUMBER OF LABELS ; ; PROCESS OPCODE ; OPC: CALL ZBUF ;ZERO WORKING BUFFER CALL SBLK ;SCAN TO OPCODE JC OERR ;FOUND CARRIAGE RETURN CALL ALPS ;PLACE OPCODE IN BUFFER CPI ' ' ;CHECK FOR BLANK AFTER OPCODE JC OPCD ;CR AFTER OPCODE JNZ OERR ;ERROR IF NO BLANK JMP OPCD ;CHECK OPCODE ; ; THIS ROUTINE CHECKS THE CHAR AFTER A LABEL FOR A BLANK ; OR A COLON ; LCHK: LHLD PNTR MOV A,M ;GET CHAR AFTER LABEL CPI ' ' ;CHECK FOR A BLANK RZ ;RETURN IF A BLANK CPI ':' ;CHECK FOR A COLON RNZ INX H SHLD PNTR ;SAVE POINTER RET ; ; PROCESS ANY PSEUDO OPS THAT NEED TO BE IN PASS 1 ; PSU1: CALL SBLK ;SCAN TO OPERAND LDAX D ;FETCH VALUE ORA A ;SET FLAGS JZ ORG1 ;ORG OPCODE JM DAT1 ;DATA STATEMENT JPO EQU1 ;EQU OP CPI 5 JC RES1 ;RES OPCODE JNZ EASS ;JUMP IF END ; DO DW PSEUDO OP ACO1: MVI C,2 ;2 BYTE INSTRUCTION XRA A ;GET A ZERO JMP OCN1 ;ADD VALUE TO PROGRAM COUNTER ; DO ORG PSEUDO OP ORG1: CALL ASCN ;GET OPERAND LDA OBUF+18 ;FETCH ERROR INDICATOR CPI ' ' ;CHECK FOR AN ERROR RNZ ;IF ERROR DON'T CHANGE PC SHLD ASPC ;STORE NEW ORIGIN LDA IBUF ;GET FIRST CHAR CPI ' ' ;CHECK FOR LABEL RZ ;NO LABEL JMP EQUS ;CHANGE LABEL VALUE ; DO EQU PSEUDO OP EQU1: CALL ASCN ;GET OPERAND LDA IBUF ;FETCH 1ST CHAR CPI ' ' ;CHECK FOR LABEL JZ ERRM ;MISSING LABEL EQUS: XCHG LHLD TABA ;SYMBOL TABLE ADDRESS MOV M,E ;STORE LABEL VALUE INX H MOV M,D JMP AOU2 ;OUTPUT IF ERROR ; DO DS PSEUDO OP RES1: CALL ASCN ;GET OPERAND MOV B,H MOV C,L JMP RES21 ;ADD VALUE TO PROGRAM COUNTER ; DO DB PSEUDO OP DAT1: JMP DAT1X ; ; PERFORM PASS 2 OF THE ASSEMBLER ; PAS2: LXI H,OBUF ;SET OUTPUT BUFFER ADDRESS LDA ASPC+1 ;FETCH PC (HIGH) CALL BINH+3 ;CONVERT FOR OUTPUT INX H LDA ASPC ;FETCH PC(LOW) CALL BINH+3 ;CONVERT FOR OUTPUT SHLD OIND ;SAVE OUTPUT ADDRESS CALL ZBUF ;CLEAR BUFFER LXI H,IBUF ;INITIALIZE LINE POINTER PABL: SHLD PNTR ;SAVE POINTER MOV A,M ;FETCH FIRST CHAR CPI ' ' ;CHECK FOR LABEL JZ OPC ;GET OPCODE CPI ';' ;CHECK FOR COMMENT RZ ;RETURN IF COMMENT CALL SLAB ;SCAN OFF LABEL JC ERRL ;ERROR IN LABEL CALL LCHK ;CHECK FOR A BLANK OR COLON JNZ ERRL ;ERROR IF NOT A BLANK JMP OPC ; ; PROCESS PSEUDO OPS FOR PASS 2 ; PSU2: LDAX D ORA A ;SET FLAGS JZ ORG2 ;ORG OPCODE JM DAT2 ;DATA OPCODE RPO ;RETURN IF EQU CPI 5 JC RES2 ;RES OPCODE JNZ EASS ;END OPCODE ; DO DW PSEUDO OP ACO2: CALL TYS6 ;GET VALUE JMP ACO1 ; DO DS PSEUDO OP RES2: CALL ASBL ;GET OPERAND MOV B,H MOV C,L LHLD BBUF+2 ;FETCH STORAGE COUNTER DAD B ;ADD VALUE SHLD BBUF+2 ;GET A ZERO RES21: XRA A JMP OCN2 ; DO DB PSEUDO OP DAT2: CALL TYS5 ;GET OPERAND DAT1X: XRA A ;GET A ZERO MVI C,1 ;BYTE COUNT JMP OCN1 ; DO ORG PSEUDO OP ORG2: CALL ASBL ;GET NEW ORIGIN LDA OBUF+18 ;GET ERROR INDICATOR CPI ' ' ;CHECK FOR AN ERROR RNZ XCHG LHLD ASPC ;FETCH PC XCHG SHLD ASPC ;STORE NEW PC MOV A,L SUB E ;FORM DIFFERENCE OF ORIGINS MOV E,A MOV A,H SBB D MOV D,A LHLD BBUF+2 ;FETCH STORAGE POINTER DAD D ;MODIFY SHLD BBUF+2 ;SAVE RET ; ; PROCESS 1 BYTE INSTRUCTIONS WITHOUT OPERANDS ; TYP1: CALL ASTO ;STORE VALUE IN MEMORY RET ; ; PROCESS STAX AND LDAX ; TYP2: CALL ASBL ;FETCH OPERAND CNZ ERRR ;ILLEGAL REGISTER MOV A,L ;GET LOW ORDER OPERAND ORA A JZ TY31 ;OPERAND = 0 CPI 2 ;OPERAND = 2 CNZ ERRR ;ILLEGAL REGISTER JMP TY31 ; ; PROCESS PUSH,POP,INX,DCX,DAD INSTRUCTIONS ; TYP3: CALL ASBL ;FETCH OPERAND CNZ ERRR ;ILLEGAL REGISTER MOV A,L ;GET LOW ORDER OPERAND RRC ;CHECK LOW ORDER BIT CC ERRR ;ILLEGAL REGISTER RAL ;RESTORE OPERAND CPI 8 CNC ERRR ;ILLEGAL REGISTER TY31: RLC ;MULTIPLY BY 8 RAL RAL TY32: MOV B,A LDAX D ;FETCH OPCODE BASE ADD B ;FORM OPCODE CPI 118 ;CHECK FOR MOV M,M CZ ERRR ;ILLEGAL REGISTER JMP TYP1 ; ; PROCESS ACCUMULATOR, INR,DCR,MOV,RST INSTRUCTION ; TYP4: CALL ASBL ;FETCH OPERAND CNZ ERRR ;ILLEGAL REGISTER MOV A,L ;GET LOW ORDER OPERAND CPI 8 CNC ERRR ;ILLEGAL REGISTER LDAX D ;FETCH OPCODE BASE CPI 64 ;CHECK MOV INSTRUCTION JZ TY41 CPI 199 MOV A,L JZ TY31 ;RST INST JM TY32 ;ACCUMULATOR INST JMP TY31 ;INR,DCR ; PROCESS MOV INSTRUCTION TY41: DAD H ;MULTIPLY OPERAND BY 8 DAD H DAD H ADD L ;FORM OPCODE STAX D ;SAVE OPCODE CALL MPNT ;INCR POINTER CALL ASCN ;GET NEXT OPERAND CNZ ERRR ;ILLEGAL REGISTER MOV A,L ;FETCH LOW ORDER OPERAND CPI 8 CNC ERRR ;ILLEGAL REGISTER JMP TY32 ; ; PROCESS IMMEDIATE INSTRUCTIONS ; IMMEDIATE BYTE CAN BE BETWEEN -256 AND +255 ; MVI INSTRUCTION IS A SPECIAL CASE AND CONTAINS 2 ARGUMENTS ; IN OPERAND ; TYP5: CPI 6 ;CHECK FOR MVI INST CZ TY56 CALL ASTO ;STORE OBJECT CODE BYTE TYS5: CALL ASBL ;GET IMMEDIATE ARGUMENT INR A CPI 2 ;CHECK OPERAND FOR RANGE CNC ERRV ;OPERAND OUT OF RANGE MOV A,L JMP TYP1 ; ; FETCH 1ST ARGUMENT FOR MVI AND LXI INSTRUCTIONS ; TY56: CALL ASBL ;FETCH ARG CNZ ERRR ;ILLEGAL REGISTER MOV A,L ;GET LOW ORDER ARGUMENT CPI 8 CNC ERRR ;ILLEGAL REGISTER DAD H ;MULTIPLY BY 8 DAD H DAD H LDAX D ;FETCH OPCODE BASE ADD L ;FORM OPCODE MOV E,A ;SAVE OBJECT BYTE MPNT: LHLD PNTR ;FETCH POINTER MOV A,M ;FETCH CHARACTER CPI ',' ;CHECK FOR COMMA INX H ;INCR POINTER SHLD PNTR JNZ ERRS ;SYNTAX ERROR IN NO COMMA MOV A,E ;GET OBJECT BYTE RET ; ; PROCESS 3 BYTE INSTRUCTIONS ; LXI IS A SPECIAL CASE ; TYP6: CPI 1 ;CHECK FOR LXI JNZ TY6 ;JUMP IF NOT LXI CALL TY56 ;GET REGISTER ANI 8 ;CHECK FOR ILLEGAL REGISTER CNZ ERRR ;REGISTER ERROR MOV A,E ;GET OPCODE ANI 0F7H ;CLEAR BIT IN ERROR TY6: CALL ASTO ;STORE OBJECT BYTE TYS6: CALL ASBL ;FETCH OPERAND MOV A,L MOV D,H CALL ASTO ;STORE 2ND BYTE MOV A,D JMP TYP1 RET ; ; THIS ROUTINE IS USED TO STORE OBJECT CODE PRODUCED ; BY THE ASSEMBLER DURING PASS 2 INTO MEMORY ; ASTO: LHLD BBUF+2 ;FETCH STORAGE ADDRESS MOV M,A ;STORE OBJECT BYTE INX H SHLD BBUF+2 LHLD OIND ;FETCH OUTPUT ADDRESS INX H INX H CALL BINH+3 ;CONVERT OBJECT BYTE SHLD OIND RET ; ; GET HERE WHEN END PSEUDO OP IS FOUND OR WHEN END OF FILE ; OCCURS IN SOURCE STATEMENTS. CONTROL IS SET FOR EITHER PASS 2 ; OR ASSEMBLY TERMINATES IF FINISHED. ; EASS: LDA PASI ;FETCH PASS INDICATOR ORA A ;SET FLAGS JNZ EOR ;JUMP IF FINISHED CALL CRLF MVI A,1 ;PASS INDICATOR FOR PASS 2 JMP ASM3 ;DO 2ND PASS ; ; THIS ROUTINE SCANS THROUGH A CHARACTER STRING UNTIL ; THE FIRST NON-BLANK CHARACTER IS FOUND ; ; ON RETURN CARRY = 1 INDICATES A CR AS FIRST NON BLANK CHARACTER ; SBLK: LHLD PNTR ;FETCH ADDRESS SBL1: MOV A,M ;FETCH CHAR CPI ' ' ;CHECK FOR A BLANK RNZ ;RETURN IF NOT BLANK SBL2: INX H SHLD PNTR ;SAVE POINTER JMP SBL1 ; ; THIS ROUTINE IS USED TO CHECK THE CONDITION CODE MNEMONICS ; FOR CONDITIONAL JUMPS, CALLS, AND RETURN. ; COND: LXI H,ABUF+1 SHLD ADDS MVI B,2 ;2 CHARACTERS CALL COPC RET ; ; THE FOLLOWING IS THE OPCODE TABLE ; OTAB: DB 'ORG',0,0 DB 'EQU',0,1 DB 'DB',0,0,-1 DB 'DS',0,0,3 DB 'DW',0,0,5 DB 'END',0,6,0 DB 'HLT',76H DB 'RLC',7 DB 'RRC',0FH DB 'RAL',17H DB 'RAR',1FH DB 'RET',0C9H DB 'CMA',2FH DB 'STC',37H DB 'DAA',27H DB 'CMC',3FH DB 'EI',0,0FBH DB 'DI',0,0F3H DB 'NOP',0,0 DB 'XCHG',0EBH DB 'XTHL',0E3H DB 'SPHL',0F9H DB 'PCHL',0E9H,0 DB 'STAX',2 DB 'LDAX',0AH,0 DB 'PUSH',0C5H DB 'POP',0,0C1H DB 'INX',0,3 DB 'DCX',0,0BH DB 'DAD',0,9,0 DB 'INR',4 DB 'DCR',5 DB 'MOV',40H DB 'ADD',80H DB 'ADC',88H DB 'SUB',90H DB 'SBB',98H DB 'ANA',0A0H DB 'XRA',0A8H DB 'ORA',0B0H DB 'CMP',0B8H DB 'RST',0C7H,0 DB 'ADI',0C6H DB 'ACI',0CEH DB 'SUI',0D6H DB 'SBI',0DEH DB 'ANI',0E6H DB 'XRI',0EEH DB 'ORI',0F6H DB 'CPI',0FEH DB 'IN',0,0DBH DB 'OUT',0D3H DB 'MVI',6,0 DB 'JMP',0,0C3H DB 'CALL',0CDH DB 'LXI',0,1 DB 'LDA',0,3AH DB 'STA',0,32H DB 'SHLD',22H DB 'LHLD',2AH,0 ; CONDITION CODE TABLE DB 'NZ',0 DB 'Z',0,8 DB 'NC',10H DB 'C',0,18H DB 'PO',20H DB 'PE',28H DB 'P',0,30H DB 'M',0,38H,0 ; ; THIS ROUTINE IS USED TO CHECK A GIVEN OPCODE AGAINST TO LEGAL ; OPCODES CONTAINED IN THE OPCODE TABLE ; COPC: LHLD ADDS LDAX D ;FETCH CHAR ORA A JZ COP1 ;JUMP IF TERMINATION CHAR MOV C,B CALL SEAR ;COMPARE STRINGS LDAX D RZ ;RETURN IF MATCH INX D ;NEXT STRING JMP COPC ;CONTINUE SEARCH COP1: INR A ;CLEAR ZERO FLAG INX D ;INCR ADDRESS RET ; ; THIS ROUTINE CHACKS THE LEGAL OPCODES IN BOTH PASS 1 AND ; PASS 2. IN PASS 1 THE PROGRAM COUNTER IS INCREMENTED BY THE ; CORRECT NUMBER OF BYTES. AN ADDRESS IS ALSO SET SO THAT ; AN INDEXED JUMP CAN BE MADE TO PROCESS THE OPCODE FOR ; PASS 2 ; OPCD: LXI H,ABUF ;SET ADDRESS SHLD ADDS LXI D,OTAB ;OPCODE TABLE ADDRESS MVI B,4 ;CHAR COUNT CALL COPC ;CHECK OPCODES JZ PSEU ;JUMP IF A PSEUDO OP DCR B ;3 CHAR OPCODES CALL COPC JZ OP1 INR B ;4 CHAR OPCODES CALL COPC OP1: LXI H,TYP1 ;TYPE 1 INST OP2: MVI C,1 ;1 BYTE INST JZ OCNT ; OPC2: CALL COPC ;CHECK FOR STAX, LDAX LXI H,TYP2 JZ OP2 CALL COPC ;CHECK FOR PUSH,POP,INX,DCX,DAD LXI H,TYP3 JZ OP2 DCR B ;3 CHAR OPCODES CALL COPC ;ACCUMULATOR INST'S,INR,DCR,MOV,RST LXI H,TYP4 JZ OP2 OPC3: CALL COPC ;IMMEDIATE INSTRUCTIONS LXI H,TYP5 MVI C,2 ;2 BYTE INSTRUCTIONS JZ OCNT INR B ;4 CHAR OPCODES CALL COPC ;JMP,CALL,LXI,LDA,STA,LHLD,SHLD OPCODES JZ OP4 CALL COND ;CONDITIONAL INSTRUCTIONS JNZ OERR ;ILLEGAL OPCODE ADI 0C0H ;ADD BASE VALUE OF RETURN MOV D,A MVI B,3 ;3 CHAR OPCODES LDA ABUF ;FETCH FIRST CHAR MOV C,A ;SAVE CHAR CPI 'R' ;CONDITIONAL RETURN MOV A,D JZ OP1 MOV A,C INR D ;FORM CONDITIONAL JUMP INR D CPI 'J' ;CONDITIONAL JUMP JZ OPAD CPI 'C' ;CONDITIONAL CALL JNZ OERR ;ILLEGAL OPCODE INR D ;FORM CONDITIONAL CALL INR D OPAD: MOV A,D ;GET OPCODE OP4: LXI H,TYP6 OP5: MVI C,3 ;3 BYTE INSTRUCTION OCNT: STA TEMP ;SAVE OPCODE ; CHECK FOR OPCODE ONLY CONTAINING THE CORRECT NUMBER OF CHARACTERS ; THUS, SAY, ADDQ WOULD GIVE AN ERROR MVI A,ABUF ;LOAD BUFFER ADDRESS ADD B ;ADD LENGTH OF OPCODE MOV E,A MVI A,ABUF SHR 8 ;LOAD BUFFER ADDRESS ACI 0 ;GET HIGH ORDER PART MOV D,A LDAX D ;FETCH CHAR AFTER OPCODE ORA A ;IS SHOULD BE ZERO JNZ OERR ;OPCODE ERROR LDA PASI ;FETCH PASS INDICATOR OCN1: MVI B,0 XCHG OCN2: LHLD ASPC ;FETCH PROGRAM COUNTER DAD B ;ADD IN BYTE COUNT SHLD ASPC ;STORE PC ORA A ;WHICH PASS RZ ;RETURN IF PASS 1 LDA TEMP ;FETCH OPCODE XCHG PCHL ; OERR: LXI H,ERRO ;SET ERROR ADDRESS MVI C,3 ;LEAVE 3 BYTES FOR PATCH JMP OCN1-3 ; PSEU: LXI H,ABUF+4 ;SET BUFFER ADDRESS MOV A,M ;FETCH CHAR AFTER OPCODE ORA A ;SHOULD BE A ZERO JNZ OERR LDA PASI ;FETCH PASS INDICATOR ORA A JZ PSU1 JMP PSU2 ; ; THIS ROUTINE IS USED TO PROCESS LABELS ; IT CHECKS WHETHER A LABEL IS IN THE SYMBOL TABLE OR NOT ; ON RETURN Z=1 MEANS A MATCH WAS FOUND AND H,L CONTAIN THE VALUE ; ASSOCIATED WITH THE LABEL. OTHERWISE D,E POINT TO THE NEXT AVAILABLE ; LOCATION IN THE TABLE. THE REGISTER NAMES A,B,C,D,E,H,L,M ; ARE PREDEFINED BY THE SYSTEM AND NEED NOT BE ENTERED BY THE USER ; ON RETURN C=1 INDICATES A LABEL ERROR ; SLAB: CPI 'A' ;CHECK FOR LEGAL CHAR RC ;RETURN IF ILLEGAL CHAR CPI 'Z'+1 CMC RC ;RETURN IF ILLEGAL CHAR CALL ALPS ;PLACE SYMBOL IN BUFFER LXI H,ABUF ;SET BUFFER ADDRESS SHLD ADDS ;SAVE ADDRESS DCR B ;CHECK IF ONE CHAR JNZ SLA1 ; CHECK IF PREDEFINED REGISTER NAME INR B ;SET B=1 LXI D,RTAB ;REGISTER TABLE ADDRESS CALL COPC ;CHECK NAME OF REGISTER JNZ SLA1 ;NOT A PREDEFINED REGISTER MOV L,A MVI H,0 ;SET VALUE (HIGH) JMP SLA2 SLA1: LDA NOLA ;FETCH SYMBOL COUNT MOV B,A LXI D,SYMT ;SET SYMBOL TABLE ADDRESS ORA A ;ARE THERE ANY LABELS JZ SLA3 ;JUMP IF NO LABELS MVI A,LLAB ;FETCH LENGTH OF TABLE STA NCHR CALL COMS ;CHECK TABLE SLA2: STC CMC ;CLEAR CARRY RET SLA3: INR A ;CLEAR ZERO FLAG ORA A ;CLEAR CARRY RET ; ; PREDEFINE REGISTER VALUES IN THIS TABLE ; RTAB: DB 'A',7 DB 'B',0 DB 'C',1 DB 'D',2 DB 'E',3 DB 'H',4 DB 'L',5 DB 'M',6 DB 0 ;END OF TABLE INDICATOR ; ; THIS ROUTINE SCANS THE INPUT LINE AND PLACES THE OPCODES AND ; LABELS IN THE BUFFER. THE SCAN TERMINATES WHEN A CHARACTER ; OTHER THAN 0-9 OR A-Z IS FOUND ; ALPS: MVI B,0 ;SET COUNT ALP1: STAX D ;STORE CHAR IN BUFFER INR B ;INCR COUNT MOV A,B ;FETCH COUNT CPI 11 ;MAX BUFFER SIZE RNC ;RETURN IF BUFFER FILLED INX D ;INCR BUFFER INX H ;INCR INPUT ADDRESS SHLD PNTR ;SAVE LINE POINTER MOV A,M ;FETCH CHAR CPI '0' ;CHECK FOR LEGAL CHAR RC CPI '9'+1 JC ALP1 CPI 'A' RC CPI 'Z'+1 JC ALP1 RET ; ; THIS ROUTINE IS USED TO SCAN THROUGH THE INPUT LINE TO ; FETCH THE VALUE OF THE OPERAND FIELD. ON RETURN THE VALUE OF THE ; OPERAND IS CONTAINED IN REGISTERS H,L ; ASBL: CALL SBLK ;GET FIRST ARGUMENT ASCN: LXI H,0 ;GET A ZERO SHLD OPRD ;INITIALIZE OPERAND INR H SHLD OPRI-1 ;INITIALIZE OPERAND INDICATOR NXT1: LHLD PNTR ;FETCH SCAN POINTER DCX H CALL ZBUF ;CLEAR BUFFER STA SIGN ;ZERO SIGN INDICATOR NXT2: INX H ;INCR POINTER MOV A,M ;FETCH NEXT CHAR CPI ' '+1 JC SEND ;JUMP IF CR OR BLANK CPI ',' ;FIELD SEPARATOR JZ SEND ; CHECK FOR OPERATORS CPI '+' ;CHECK FOR PLUS JZ ASCI CPI '-' ;CHECK FOR MINUS JNZ ASC2 STA SIGN ASCI: LDA OPRI ;FETCH OPERAND INDICATOR CPI 2 ;CHECK FOR TWO OPERATORS JZ ERRS ;SYNTAX ERROR MVI A,2 STA OPRI ;SET INDICATOR JMP NXT2 ; CHECK FOR OPERANDS ASC2: MOV C,A ;SAVE CHAR LDA OPRI ;GET INDICATOR ORA A ;CHECK FOR TWO OPERANDS JZ ERRS ;SYNTAX ERROR MOV A,C CPI '$' ;LC EXPRESSION JNZ ASC3 INX H SHLD PNTR ;SAVE POINTER LHLD ASPC ;FETCH LOCATION COUNTER JMP AVAL ; CHECK FOR ASCII CHARS ASC3: CPI 27H ;CHECK FOR SINGLE QUOTE JNZ ASC5 ;JUMP IF NOT QUOTE LXI D,0 ;GET A ZERO MVI C,3 ;CHAR COUNT ASC4: INX H ;INCR POINTER SHLD PNTR ;SAVE MOV A,M ;FETCH NEXT CHAR CPI ASCR ;IS IT CR? JZ ERRA ;ARGUMENT ERROR CPI 27H ;IS IT A QUOTE? JNZ SSTR INX H SHLD PNTR ;SAVE POINTER MOV A,M ;FETCH NEXT CHAR CPI 27H ;CHECK FOR 2 QUOTES IN A ROW JNZ AVAL+1 ;TERMINAL QUOTE SSTR: DCR C ;CHECK COUNT JZ ERRA ;TOO MANY CHARS MOV D,E MOV E,A ;SET CHAR IN BUFFER JMP ASC4 ASC5: CPI '0' ;CHECK FOR NUMERIC JC ERRA ;ILLEGAL CHAR CPI '9'+1 JNC ALAB CALL NUMS ;GET NUMERIC VALUE JC ERRA ;ARGUMENT ERROR AVAL: XCHG LHLD OPRD ;FETCH OPERAND XRA A ;GET A ZERO STA OPRI ;STORE IN OPERAND INDICATOR LDA SIGN ;GET SIGN INDICATOR ORA A ;SET FLAGS JNZ ASUB DAD D ;FORM RESULT ASC7: SHLD OPRD ;SAVE RESULT JMP NXT1 ASUB: MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A JMP ASC7 ALAB: CALL SLAB JZ AVAL JC ERRA ;ILLEGAL SYMBOL JMP ERRU ;UNDEFINED SYMBOL ; ; GET HERE WHEN TERMINATION CHARACTER IS FOUND. BLANK, COMMA, CR. ; CHECK FOR LEADING FIELD SEPARATOR ; SEND: LDA OPRI ;FETCH OPERAND INDICATOR ORA A ;SET FLAGS JNZ ERRS ;SYNTAX ERROR LHLD OPRD SEN1: MOV A,H ;GET HIGH ORDER BYTE LXI D,TEMP ;SET ADDRESS ORA A ;SET FLAGS RET ; ; GET A NUMERIC VALUE WHICH IS EITHER HEXADECIMAL OR DECIMAL ; ON RETURN CARRY SET INDICATES AN ERROR ; NUMS: CALL ALPS ;GET NUMERIC DCX D LDAX D ;GET LAST CHAR LXI B,ABUF ;SET BUFFER ADDRESS CPI 'H' ;IS IT HEX JZ NUM2 CPI 'D' ;IS IT DECIMAL JNZ NUM1 XRA A ;GET A ZERO STAX D ;CLEAR D FROM BUFFER NUM1: CALL ADEC ;CONVERT DECIMAL VALUE RET NUM2: XRA A STAX D ;CLEAR H FROM BUFFER CALL AHEX ;CONVERT HEX RET ; PROCESS REGISTER ERROR ERRR: MVI A,'R' ;GET INDICATOR LXI H,0 STA OBUF+18 ;SET IN OUTPUT BUFFER RET ; PROCESS SYNTAX ERROR ERRS: MVI A,'S' STA OBUF+18 LXI H,0 RET ; PROCESS UNDEFINED SYMBOL ERROR ERRU: MVI A,'U' JMP ERRS+2 ; PROCESS VALUE ERROR ERRV: MVI A,'V' JMP ERRR+2 ; PROCESS MISSING LABEL ERROR ERRM: MVI A,'M' STA OBUF+18 CALL AOU1 RET ; PROCESS ARGUMENT ERROR ERRA: MVI A,'A' JMP ERRS+2 ; PROCESS OPCODE ERROR ; STORE 3 BYTES OF ZERO IN OBJECT CODE TO PROVIDE FOR PATCH ERRO: MVI A,'O' STA OBUF+18 LDA PASI ;FETCH PASS INDICATOR ORA A RZ ;RETURN IF PASS 1 MVI C,3 ;NEED 3 BYTES ERO1: XRA A ;GET A ZERO CALL ASTO ;PUT IN LISTING AND MEMORY DCR C JNZ ERO1 RET ; PROCESS LABEL ERROR ERRL: MVI A,'L' JMP ERRO+2 ; PROCESS DUPLICATE LABEL ERROR ERRD: MVI A,'D' STA OBUF+18 CALL AOUT JMP OPC ; ; ; DEFINE INPUT AND OUTPUT PORTS ; USTA EQU 0 ;UART STATUS UDAI EQU 1 ;DATA IN UDAO EQU 1 ;DATA OUT PDAI EQU 6 ;PROM DATA IN PADO EQU 7 ;PROM ADDRESS OUT PDAO EQU 8 ;PROM DATA OUT PCTO EQU 9 ;PROM CONTROL OUT SWCH EQU 0FFH ; ; FILE AREA PARAMETERS ; MAXFIL EQU 6 ;MAX # OF FILES NMLEN EQU 5 ;NAME LENGTH FELEN EQU NMLEN+8 ;DIRECTORY ENTRY LENGTH FILE0: DS NMLEN BOFP: DS 2 EOFP: DS 2 MAXL: DS 4 FILTB: DS (MAXFIL-1)*FELEN INSP: DS 2 ;INSERT LINE POSITION DELP EQU INSP ;DELETE LINE POSITION ASCR EQU 13 ;ASCII CARRIAGE RETURN VALUE HCON: DS 2 ADDS EQU HCON ;FIND ADDRESS FBUF: DS NMLEN ;FILE NAME BUFFER FREAD: DS 2 ;FREE ADDRESS IN DIRECTORY FEF: DS 1 ;FREE ENTRY FOUND FLAG FOCNT EQU FEF ;OUTPUT COUNTER ABUF: DS 12 ;ASCII BUFFER BBUF: DS 4 ;BINARY BUFFER SCNT: DS 1 DCNT: DS 1 ;DUMP ROUTINE COUNTER NCOM EQU 10 ;NUMBER OF COMMANDS TABA: DS 2 ;SYMBOL TABLE END ADDRESS ASPC: DS 2 ;ASSEMBLER PROGRAM COUNTER PASI: DS 1 ;PASS INDICATOR NCHR: DS 1 ;LENGTH OF STRING FOR COMPARE PNTR: DS 2 ;LINE POINTER STORAGE NOLA: DS 1 ;NUMBER OF LABELS SIGN: DS 1 ;SIGN STORAGE FOR SCAN OPRD: DS 2 ;OPERAND STORAGE OPRI: DS 1 ;OPERAND FOUND INDICATOR TEMP: DS 1 APNT EQU INSP ;ASSEMBLER LINE POINTER AERR EQU SCNT ;ASSEMBLER ERROR PRINT SWITCH OIND: DS 2 ;OUTPUT ADDRESS LLAB EQU 5 ;LENGTH OF LABELS AREA: DS 18 OBUF: DS 25 ;OUTPUT BUFFER AREA DS 5 IBUF: DS 83 SYMT EQU $ ;START OF SYMBOL TABLE END