; ; Program: DASM ; Version: 1.5 ; Author: Richard Conn ; Date: 16 Aug 82 ; Previous Versions: 1.3 (23 May 82), 1.4 (12 June 82) ; Previous Versions: 1.0 (1 May 82), 1.1 (8 May 82), 1.2 (15 May 82) ; Derivation: ZZSOURCE and RESOURCE ; ; DASM is a TDL/ZILOG Disassembler derived from Dave Barker's ; ZZSOURCE and Ward Christensen's RESOURCE by Richard Conn. Refer to ; the documentation on RESOURCE and the built-in HELP data for information ; on the commands used for DASM. A Help file is also being planned for DASM. ; VERS equ 15 ; Version Number .Z80 ; USE ZILOG MNEMONICS ASEG ; USE ABSOLUTE SEGMENTS ; Values for TRUE and FALSE FALSE equ 0 TRUE equ NOT FALSE ; Set one and ONLY one of the following to TRUE ZILOG equ TRUE TDL equ FALSE ; Initial Values for DASM RDCOMQ EQU FALSE ;TRUE OF QUERY USER TO READ COM FILE ; WHEN 'ALL' IS FILE TYPE CTLTBL EQU ENDALL ;BEGINNING OF CONTROL TABLE SYMTAB EQU CTLTBL+600H ;BEGINNING OF SYMBOL TABLE INITOFF EQU SYMTAB+2000H ;INITIAL OFFSET VALUE COMTBL EQU INITOFF+4000H ;BEGINNING OF COMMENTS SYMMAX EQU 12 ;MAX NUMBER OF CHARS/SYMBOL (<= 12) INITLCNT EQU 20 ;NUMBER OF LINES TO DISPLAY VIA L, A, B INITDLEN EQU 80H ;NUMBER OF BYTES TO DISPLAY VIA D INITPC EQU 100H ;INITIAL VALUE OF PC INITELST EQU 0FFFFH ;INITIAL END OF LIST VALUE IBUFLEN EQU 80 ;LENGTH OF INPUT LINE BUFFER ; CP/M Constants WBOOT EQU 00H BDOS EQU 05H FCB EQU 5CH FCBNR EQU 7CH FCBTYPE EQU 65H RECLEN EQU 80H ; ; Beginning of Program ; ORG 0100H JP START JP GETCMD ;This is an easy entry point for a restart. ; ; The following INCLUDE is used to include the appropriate file defining ; the Mnemonics for the desired language. Choices at this time are: ; DASMZLG.MAC -- ZILOG-Standard Mnemonics ; DASMTDL.MAC -- TDL Mnemonics ; IF ZILOG INCLUDE DASMZLG.MAC ;Include ZILOG Mnemonic File ENDIF IF TDL INCLUDE DASMTDL.MAC ;Include TDL Mnemonic File ENDIF ; ; PRINT HEADERS ; START: LD SP,OLDST ;SET STACK CALL PSTRNG DEFB 0DH,0AH,'DASM, Version ' DEFB VERS/10+'0','.',(VERS MOD 10)+'0',0DH,0AH,0 ; ; PERFORM REENTRANT INITIALIZATION ; CALL INIT0 ;INITIALIZE BUFFERS SO DASM IS REENTRANT CALL INIT ;CLEANUP INITIALIZATION ; ; READ IN ALL FILES IF A FILE WAS SPECIFIED ; LD A,(FCB+1) ;GET FIRST LETTER OF FILE NAME CP ' '+1 ;VALID CHAR? JR C,SIGNON ;SKIP READ IF NOT VALID CHAR CALL PSTRNG DEFB 0DH,0AH,'Reading in All Files for ',0 LD HL,FCB+1 ;PT TO FILE NAME LD B,8 ;8 CHARS ARDNAME: LD A,(HL) ;GET CHAR CALL COUT ;PRINT IT INC HL ;PT TO NEXT DJNZ ARDNAME CALL ALLRD ;READ IN ALL FILES CALL PSTRNG DEFB 0DH,0AH,'-- Read Complete --',0DH,0AH,0 ; ; PRINT REST OF SIGNON MESSAGE ; SIGNON: LD DE,HEADER ;PRINT HEADER FROM INCLUDE FILE LD C,9 CALL BDOS CALL PSTRNG ;PRINT INITIAL INFO DEFB 0DH,0AH,'Type H for Help, ? for Stats',0DH,0AH,0 JR GETCMD ;PERFORM COMMAND PROCESSING ; ; CLEAN UP DASM AND COMPLETELY REINITIALIZE ; CLEAN: CALL INIT ;DO INITIALIZATION ; ; MAIN COMMAND PROCESSING LOOP ; GETCMD: XOR A ;A=0 LD (WRTENAB),A ;DISABLE OUTPUT TO FILE LD (HUSH),A ;SET NOT QUIET LD (XCPTR),A LD (XCPTR+1),A LD SP,OLDST ;RESET STACK ; ; INPUT COMMAND LINE AND CAPITALIZE ; CALL PROMPT ;INPUT COMMAND LINE VIA BDOS ; ; PROCESS COMMAND LINE ; PRCEDE: LD A,(INBUF+2) ;PT TO FIRST CHAR OF COMMAND LINE LD B,A ;GET IT LD DE,CMDTABL ;PT TO COMMAND TABLE PRCLOOP: LD A,(DE) ;GET COMMAND FROM COMMAND TABLE OR A ;END OF TABLE IF 0 JR Z,WHAT ;TELL USER THAT COMMAND WAS INVALID INC DE ;PREP FOR NO MATCH INC DE ;...PT TO NEXT COMMAND INC DE CP B ;MATCH? JR NZ,PRCLOOP ;CONTINUE LOOPING IF NOT DEC DE ;PT TO ADDRESS LD A,(DE) ;GET ADR HIGH LD B,A ;... IN B DEC DE ;PT TO LOW LD A,(DE) ;GET ADR LOW LD C,A ;... IN C PUSH BC ;ADDRESS ON STACK RET ;"JUMP TO" COMMAND ; ; GENERAL ERROR ; WHAT: XOR A LD (WRTENAB),A LD (HUSH),A CALL PSTRNG DEFB 0DH,0AH,'** Command Error **',0DH,0AH,0 JR GETCMD ; ; COMMAND TABLE -- CONTAINS COMMAND LETTER FOLLOWED BY ADDRESS OF ROUTINE ; AND ENDS IN 0 AS THE NEXT COMMAND LETTER ; CMDTABL: DEFB 0DH ;EMPTY LINE DEFW GETCMD DEFB ';' ;COMMENTS DEFW CMNT DEFB 'A' ;BUILD ASCII DEFW ASCASM DEFB 'B' ;BUILD LABELS DEFW BLDASM DEFB 'C' ;CONTROL TABLE DEFW CTL DEFB 'D' ;MEMORY DUMP DEFW DUMP DEFB 'E' ;ENTER SYMBOL DEFW ENTER DEFB 'F' ;FIND LABEL DEFW FIND DEFB 'H' ;HELP DEFW HELP DEFB 'I' ;INCREMENT SYMBOL VALUES DEFW INCMNT DEFB 'K' ;KILL SYMBOL DEFW KILL DEFB 'L' ;LIST CODE DEFW LIST DEFB 'O' ;SET OFFSET DEFW SETOS DEFB 'P' ;GENERATE PROLOG DEFW PROLOG DEFB 'Q' ;QUIET MODE DEFW QUIET DEFB 'R' ;READ FILES DEFW READ DEFB 'S' ;SAVE FILES DEFW SAVE DEFB 'U' ;SET COMMENTS DEFW UAREA DEFB 'X' ;PURGE SYMBOLS AND CONTROL DEFW PURGE DEFB 'Z' ;CLOSE ASM FILE DEFW CLOSE DEFB '?' ;STATISTICS DISPLAY DEFW STAT DEFB 0 ;END OF COMMAND TABLE ; ;COMMAND: H ; PRINT HELP INFORMATION ; HELP: CALL PSTRNG ;JUST ONE BIG PRINT ;LINE 1 DEFB 0DH,0AH,' HELP on DASM -- Command Summary' ;LINE 2 DEFB 0DH,0AH,';addr,comment Enter Comment at addr ' DEFB ';addr List comment at addr' ;LINE 3 DEFB 0DH,0AH,'; List Comments Table ' DEFB ';addr, Delete Comment' ;LINE 4 DEFB 0DH,0AH,'A (see L) Attempt to find DB''s ' DEFB 'B (see L) Build Symbol Table' ;LINE 5 DEFB 0DH,0AH,'C Dump Control Table ' DEFB 'Cnnnn Dump Ctrl Table at nnnn' ;LINE 6 DEFB 0DH,0AH,'Cnnnn,x Set Ctrl (x=BEHISW) ' DEFB 'Dnnnn Dump from nnnn on' ;LINE 7 DEFB 0DH,0AH,'Daaaa,bbbb Dump over range ' DEFB 'D,bbbb Dump thru bbbb' ;LINE 8 DEFB 0DH,0AH,'D Dump 80H more ' DEFB 'D=nn Set Dump Size Default' ;LINE 9 DEFB 0DH,0AH,'DS Dump the Symbol Table ' DEFB 'DS.symbol Dump starting at symbol' ;LINE 10 DEFB 0DH,0AH,'Ennnn,.symbol Enter symbol into table ' DEFB 'Fnnnn,ssss Find nnnn after ssss' ;LINE 11 DEFB 0DH,0AH,'F or Fnnnn Cont Find or Find nnnn ' DEFB 'Issss,oooo Inc addrs>=ssss by oooo' ;LINE 12 DEFB 0DH,0AH,'K.symbol Kill symbol from table ' DEFB 'L List next ' DEFB (INITLCNT/10)+'0',(INITLCNT MOD 10)+'0' DEFB ' lines' ;LINE 13 DEFB 0DH,0AH,'Lssss,eeee List over range ' DEFB 'L,eeee List to eeee' ;LINE 14 DEFB 0DH,0AH,'Lssss List ' DEFB (INITLCNT/10)+'0',(INITLCNT MOD 10)+'0' DEFB ' lines from ssss ' DEFB 'L=nn[,others] Set list default' ;LINE 15 DEFB 0DH,0AH,'O Print current offset ' DEFB 'Onnnn Set new offset' ;LINE 16 DEFB 0DH,0AH,'Pssss,eeee Generate program prolog ' DEFB 'Q Quiet prefix' ;LINE 17 DEFB 0DH,0AH,'Rfilename.COM Read file @ offset+100H ' DEFB 'Rfilename.CTL Read Control Table' ;LINE 18 DEFB 0DH,0AH,'Rfilename.SYM Read Symbol Table ' DEFB 'Rfilename.DOC Read Comments Table' ;LINE 19 DEFB 0DH,0AH,'Rfilename.ALL Read CTL, SYM, DOC, COM ' DEFB 'Sfilename.ASM Save ASM File' ;LINE 20 DEFB 0DH,0AH,'Sfilename.CTL Save CTL File ' DEFB 'Sfilename.SYM Save SYM File' ;LINE 21 DEFB 0DH,0AH,'Sfilename.DOC Save DOC File ' DEFB 'Sfilename.ALL CTL, SYM, DOC, ASM' ;LINE 22 DEFB 0DH,0AH,'Unnnn Set Comment Table addr ' DEFB 'X Restart DASM' ;LINE 23 DEFB 0DH,0AH,'Z Write EOF to ASM File ' DEFB '? Print Statistics' ;LINE 24 DEFB 0DH,0AH,0 JP GETCMD ; ;COMMAND: X ; PURGE ALL SYMBOLS AND CONTROL ; PURGE: CALL PSTRNG ;PROMPT USER DEFB 'Restart DASM (Y/N)? ',0 CALL CHIN ;GET SINGLE CHAR AND CAP CP 'Y' JP NZ,GETCMD CALL PSTRNG ;PRINT FUNCTION DEFB 'Restarting DASM',0DH,0AH,0 JP CLEAN ;RESTART DASM AT INIT ; ; INPUT A SINGLE CHAR IN A VIA THE BDOS AND CAPITALIZE IT; FOLLOW WITH ; CHIN: LD C,1 ;GET CHAR FROM CON: CALL BDOS AND 5FH ;CAPITALIZE PUSH AF CALL CRLF POP AF RET ; ;COMMAND: P ; ENTER PROLOG INTO ASSEMBLY LANGUAGE PROGRAM ; PROLOG: LD HL,INBUF+3 ;PT TO STARTING ADDRESS LD A,(HL) ;NO ADDRESS SPECIFIED? CP 0DH ;ERROR IF SO JP Z,WHAT CALL CNVRT ;CONVERT ADDRESS VALUE TO BINARY IN DE CP ' ' ;CHAR AFTER ADDRESS = ? JR Z,PRLG0 ;CONT IF SO CP ',' ;CHAR AFTER ADDRESS = ','? JP NZ,WHAT ;ERROR IF NOT ',' OR PRLG0: INC HL ;PT TO 2ND ADDRESS PUSH DE ;SAVE FIRST ADDRESS ON STACK PUSH HL ;SAVE PTR TO 2ND ADDRESS LD A,1 ;TURN ON DISK OUTPUT LD (WRTENAB),A CALL PSTG ;PRINT NEW ORG DEFB 9,'ORG',9,0 POP HL POP DE LD A,D ;ORG AT FIRST ADDRESS CALL PASHEX ;PRINT AS 'nnH' LD A,E CALL PHEX LD A,'H' CALL COUT CALL CRLF PUSH DE ;SAVE FIRST ADDRESS CALL CNVRT ;GET 2ND ADDRESS IN DE CP 0DH ;ERROR IF JP NZ,WHAT POP BC ;BC=START ADDRESS, DE=END ADDRESS LD HL,SYMTAB ;PT TO SYMBOL TABLE PRLG1: INC HL ;SKIP OVER SYMBOL ADDRESS INC HL LD A,(HL) ;GET 1ST CHAR OF SYMBOL OR A ;END OF SYMBOL TABLE? (CHAR COUNT = 0) JP Z,GETCMD ;DONE IF SO DEC HL ;PT TO SYMBOL ADDRESS DEC HL LD A,(HL) ;COMPARE SYMBOL ADDRESS TO CURRENT ADDRESS SUB C ;... IN BC INC HL LD A,(HL) SBC A,B JR C,GENEQU ;GENERATE EQU IF SYMBOL < START ADDRESS DEC HL ;PT TO SYMBOL LOW-ORDER ADDRESS AGAIN LD A,(HL) ;COMPARE SYMBOL ADDRESS TO END ADDRESS SUB E INC HL LD A,(HL) SBC A,D JP C,WITHIN ;PROCESS NORMALLY IF START <= SYMBOL <= END ; ; SYMBOL IS NOT IN RANGE OF: ; START ADDRESS <= SYMBOL <= END ADDRESS ; GENERATE EQUATE FOR IT ; GENEQU: PUSH HL ;SAVE PTR TO SYMBOL PUSH BC ;SAVE START ADDRESS INC HL ;PT TO SYMBOL CHAR COUNT LD B,(HL) ;B=CHAR COUNT PUSH HL ;SAVE PTR TO CHAR COUNT INC HL ;PT TO FIRST LETTER OF SYMBOL LD A,(HL) ;GET IT DEC HL ;PT BACK TO CHAR COUNT CP 'A' ;IF FIRST LETTER IS LESS THAN A, DON'T GENERATE 'EQU' JR C,PRLG3 ; ; SCAN SYMBOL FOR '+' OR '-' AND DON'T GENERATE 'EQU' IF IT CONTAINS ONE ; PRLG2: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CP '+' ;CHECK JR Z,PRLG3 CP '-' ;CHECK JR Z,PRLG3 DJNZ PRLG2 ;LOOP POP HL ;GET PTR TO SYMBOL CHAR COUNT LD B,(HL) ;B=CHAR COUNT LD A,1 ;ENABLE DISK OUTPUT LD (WRTENAB),A ; ; PRINT SYMBOL EQUATE; HL PTS TO BYTE BEFORE SYMBOL AND B=NUMBER OF CHARS ; LOOPB: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CALL COUT ;PRINT IT DJNZ LOOPB ;LOOP FOR NUMBER OF CHARS IN B CALL PSTG DB 9,'EQU',9,0 POP BC ;GET START ADR POP HL ;PT TO CHAR COUNT OF CURRENT SYMBOL LD A,(HL) ;CHECK FOR HIGH-ORDER VALUE OR A ;DON'T PRINT SIGNIFICANT ZERO CALL NZ,PASHEX DEC HL ;PT TO LOW-ORDER VALUE LD A,(HL) ;GET IT CALL PHEX ;PRINT IT LD A,'H' ;FOLLOWING 'H' FOR 'nnH' AND NEW LINE CALL COUT CALL CRLF XOR A ;DISABLE WRITE TO DISK LD (WRTENAB),A INC HL ;PT TO HIGH-ORDER VALUE OF SYMBOL ; ; SYMBOL IS WITHIN THE DESIRED RANGE (START <= SYMBOL <= END) ; WITHIN: INC HL ;PT TO CHAR COUNT OF SYMBOL LD A,(HL) ;GET IT CALL SKIP ;SKIP TO NEXT SYMBOL INC HL ;PT TO ITS ADDRESS CALL BRKCHK ;CHECK FOR BREAK JP PRLG1 ;CONTINUE GENERATING PROLOG ; ; SKIP CURRENT SYMBOL FOR ONE REASON OR ANOTHER ; PRLG3: POP HL ;RESTORE REGS AND CONTINUE POP BC POP HL JR WITHIN ; ;COMMAND: Q PREFIX ; EXECUTE THE COMMAND IN THE QUIET MODE ; QUIET: LD A,1 ;TURN ON QUIET MODE LD (HUSH),A LD DE,INBUF+2 ;COPY COMMAND LINE LEFT 1 CHARACTER LD HL,INBUF+3 SHFTBF: LD A,(HL) ;COPY IN ORDER TO CONTINUE PROCESSING LD (DE),A ;... NORMALLY INC HL INC DE CP 0DH JR NZ,SHFTBF JP PRCEDE ;RETURN TO MAIN COMMAND PROCESSOR ; ;COMMAND: D ; DUMP THE MEMORY, SYMBOL TABLE, OR SET THE DEFAULT DUMP LENGTH ; DUMP: LD HL,(DMPSTRT) ;GET PTR TO STARTING ADR FOR DUMP PUSH HL EX DE,HL ;... IN DE LD HL,(DMPLEN) ;GET DEFAULT LENGTH OF DUMP ADD HL,DE ;CALCULATE END ADDRESS OF DUMP LD (DMPEND),HL ;SAVE IT POP DE LD HL,INBUF+3 ;LOOK AT COMMAND LINE LD A,(HL) ;GET CHAR AFTER THE 'D' CP 0DH ;IF , THEN DUMP FROM DMPSTRT TO DMPEND JP Z,DMPHDR CP 'S' ;IF S, THEN DUMP THE SYMBOL TABLE JP Z,DMPSYM CP '=' ;IF =, THEN SET THE DEFAULT DUMP LENGTH JP Z,DUMP5 CP ',' ;IF ',', THEN DUMP FROM CURRENT TO END SPEC JP Z,DUMP1 ; ; NUMBER SHOULD FOLLOW THE D -- PROCESS IT ; DUMP0: CALL CNVRT ;GET VALUE PUSH HL ;SAVE IT LD HL,(DMPLEN) ;GET DEFAULT LENGTH ADD HL,DE ;COMPUTE END OF DUMP LD (DMPEND),HL ;SAVE IT POP HL ;GET START ADDRESS OF DUMP ; ; CHECK FOR DELIMITER AFTER FIRST NUMBER ; DUMP1: CP 0DH ;IF , DUMP FOR THE DEFAULT LENGTH JR Z,DUMP3 CP ' ' ;IF , GET 2ND NUMBER JR Z,DUMP2 CP ',' ;IF ',', GET 2ND NUMBER JP NZ,WHAT ;ERROR IF NOT ; ; EXTRACT 2ND NUMBER FROM DUMP COMMAND ; DUMP2: INC HL ;PT TO NUMBER PUSH DE CALL CNVRT ;RETURN IT IN DE EX DE,HL LD (DMPEND),HL ;SET END ADDRESS OF DUMP POP DE ;GET START ADDRESS OF DUMP IN DE ; ; ADD OFFSET TO BEGINNING AND ENDING DUMP ADDRESSES ; ON INPUT, DE=START OF DUMP ADDRESS ; DUMP3: LD HL,(OFFSET) ;GET OFFSET PUSH HL ;SAVE IT ADD HL,DE ;ADD TO BEGINNING DUMP ADDRESS LD (DMPSTRT),HL ;SET PTR LD HL,(DMPEND) ;GET END ADDRESS OF DUMP POP DE ;GET OFFSET IN DE ADD HL,DE ;ADD OFFSET TO END ADDRESS OF DUMP LD (DMPEND),HL ;NEW END ADDRESS OF DUMP CP 0DH ;MAKE SURE AFTER DUMP COMMAND JP NZ,WHAT ;ERROR IF NOT ; ; PRINT HEADER FOR DUMP AND THEN PERFORM DUMP ; DMPHDR: CALL PSTRNG ;PRINT A HEADER FOR THE DUMP DEFB 'Addr +0 +2 +4 +6 +8 +A +C +E ASCII' DEFB 0DH,0AH,0 ; ; MAIN DUMP LOOP ; CNTDMP: LD HL,(DMPSTRT) ;GET START ADDRESS OF DUMP DUMP4: CALL BRKCHK ;CHECK FOR BREAK PUSH HL ;SAVE PTR TO NEXT BYTE CALL TWOS ;MAKE HL CONTAIN RELATIVE VALUE CALL PVALUE ;... BY SUBTRACTING OFFSET; THEN PRINT IT POP HL ;GET PTR PUSH HL ;SAVE PTR CALL SPACE ;PRINT A SPACE ; ; DUMP AS HEX ; DMPLN: LD A,(HL) ;GET BYTE CALL PHEX ;PRINT AS HEX INC HL ;PT TO NEXT LD A,L ;PRINT ONE SPACE FOR EVERY 2 VALUES AND 1 CALL Z,SPACE LD A,L ;PRINT TWO SPACES EVERY 4 AND 3 CALL Z,SPACE LD A,L ;PRINT THREE SPACES EVERY 8 AND 7 CALL Z,SPACE LD A,L ;CHECK FOR END OF DUMP LINE (EVERY 16) AND 0FH JR NZ,DMPLN LD A,'!' ;PRINT BEGINNING '!' CALL COUT POP HL ;GET PTR TO FIRST BYTE ; ; DUMP AS ASCII ; DMPASC: LD A,(HL) ;GET CHAR CP ' ' ;PRINT . IF LESS THAN JR C,PERIOD CP 7FH ;PRINT . IF GREATER THAN JR C,CHRCTR ; ; PRINT '.' ; PERIOD: LD A,'.' ; ; PRINT CHAR IN A AND ADVANCE FOR UP TO 16 CHARS ; CHRCTR: CALL COUT ;PRINT CHAR INC HL ;PT TO NEXT LD A,L ;END OF LINE? AND 0FH ;EVERY 16 JR Z,LCMPLT ;DONE IF SO AND 7 ;EXTRA SPACE FOR EVERY 8 CALL Z,SPACE JR DMPASC ;CONTINUE ASCII DUMP ; ; TIDY UP THE LINE ; LCMPLT: LD A,'!' ;PRINT ENDING '!' CALL COUT CALL CRLF ;NEW LINE LD (DMPSTRT),HL ;COMPARE CURRENT START ADDRESS TO END ADDRESS LD A,(DMPEND) SUB L LD A,(DMPEND+1) SBC A,H JR NC,DUMP4 ;CONTINUE IF CURRENT START <= END JP GETCMD ;RETURN TO COMMAND PROCESSING OTHERWISE ; ; SET THE DEFAULT NUMBER OF BYTES TO DUMP ; DUMP5: INC HL ;PT TO VALUE CALL CNVRT ;RETURN VALUE IN DE INC HL DEC DE EX DE,HL LD (DMPLEN),HL ;SAVE VALUE EX DE,HL CP ',' JP Z,DUMP0 CP ' ' JP Z,DUMP0 CP 0DH JP Z,GETCMD JP WHAT ; ; DS -- DUMP THE SYMBOL TABLE ; DMPSYM: CALL IECNT ;INIT ECNT LD HL,INBUF+4 ;PT TO CHAR AFTER 'DS' LD A,(HL) ;GET IT CP '.' ;SYMBOL SPECIFIED? JR NZ,FRMBGN ;NO, SO DUMP FROM BEGINNING OF TABLE CALL LNGTH ;COMPUTE LENGTH OF GIVEN SYMBOL CALL PLCSYM ;RETURN PTR TO THIS SYMBOL IN HL JR NC,FRMSYM ;PROCESS NORMALLY IF FOUND LD HL,(SYMRKR) JR FRMSYM FRMBGN: LD HL,SYMTAB ;PT TO TABLE FRMSYM: LD E,(HL) ;GET ADDRESS OF SYMBOL IN DE INC HL LD D,(HL) INC HL LD A,(HL) ;GET LENGTH OF SYMBOL IN A OR A ;DONE IF LENGTH = 0 JP Z,SPITCR EX DE,HL ;PRINT VALUE OF SYMBOL CALL PVALUE EX DE,HL LD A,'=' ;PRINT = CALL COUT LD B,(HL) ;GET LENGTH OF SYMBOL IN B LD A,SYMMAX+1 ;COMPUTE DIFF FROM MAX SUB B LD C,A ;DIFFERENCE IN C (NUMBER OF SPACES AFTER SYM) INC HL ; ; PRINT THE SYMBOL PTED TO BY HL; B=NUMBER OF BYTES LONG THE SYMBOL IS ; SPIT: LD A,(HL) ;GET SYMBOL CHAR CALL COUT ;PRINT IT INC HL ;PT TO NEXT DJNZ SPIT ;UNTIL DONE ; ; PRINT TRAILING SPACES AFTER SYMBOL ; LD B,C ;SP COUNT IN B SPIT1: CALL SPACE DJNZ SPIT1 CALL SPCRLF ;NEW LINE CALL BRKCHK ;CHECK FOR BREAK JR FRMSYM ;CONTINUE ; ; PRINT AND EXIT ; SPITCR: CALL CRLF ;NEW LINE JP GETCMD ; ; COUNT DOWN ECNT AND OUTPUT ON ZERO ; SPCRLF: LD A,(ECNT) ;GET COUNT DEC A LD (ECNT),A RET NZ CALL CRLF ;NEW LINE ; ; INIT ECNT ; IECNT: LD A,4 ;SET 4 ENTRIES LD (ECNT),A RET ; ; PRINT THE VALUE OF THE OFFSET. ; PRNTOS: CALL PSTRNG DB 'Offset = ',0 LD HL,(OFFSET) ;GET IT AND PRINT IT CALL PVALUE CALL CRLF ;NEW LINE JP GETCMD ; ;COMMAND: O ; SET OR PRINT OFFSET ADDRESS ; SETOS: LD HL,INBUF+3 ;FORMAT: O c/r LD A,(HL) ;.. or Oxxxx c/r CP 0DH ;IF JUST O, DO IT VIA PRNTOS JR Z,PRNTOS CALL CNVRT ;GET VALUE IN DE CP 0DH ;ERROR? JP NZ,WHAT EX DE,HL ;SAVE AS OFFSET LD (OFFSET),HL CALL CRLF ;NEW LINE AND PRINT NEW VALUE JR PRNTOS ; ; SET UP THE FILE CONTROL BLOCK. ; SETFCB: LD A,(FOPEN) ;FILE OPEN? OR A ;0 IF NOT JP NZ,CANT LD (FCB),A ;SET DEFAULT DRIVE LD (FCB+12),A ;SET EXTENT NUMBER TO ZERO LD HL,INBUF+3 ;PT TO FIRST LETTER OF POSSIBLE FILE NAME LD A,(INBUF+4) ;GET SECOND LETTER CP ' ' ;ERROR IF JUST JP Z,WHAT CP ':' ;GET AND SET DRIVE IF ':' JR NZ,SMDRV LD A,(HL) ;GET SPECIFIED DRIVE SUB '@' ;CONVERT IT TO BINARY LD (FCB),A ;SET DRIVE NUMBER IN FCB INC HL INC HL ; ; WRITE FILE NAME AND TYPE INTO FCB ; SMDRV: LD DE,FCB+1 ;PT TO FILE NAME FIELD OF FCB LD B,8 CALL SLIDE ;PUT FILE NAME LD B,3 CALL SLIDE ;PUT FILE TYPE RET ; ; WRITE CHARS PTED TO BY HL INTO BUFFER PTED TO BY DE; WRITE AT MOST B ; CHARS, AND FILL THE BUFFER PTED TO BY DE ; SLIDE: LD A,(HL) ;GET NEXT CHAR CP 0DH ;DONE? JR Z,BLANK ;BLANK FILL IF SO INC HL ;PT TO NEXT CP '.' ;FILE TYPE FOLLOWS? JR Z,BLANK ;BLANK FILL IF SO LD (DE),A ;PUT CHAR INC DE ;PT TO NEXT DJNZ SLIDE ;COUNT DOWN ; ; CHECK FOR ERROR IF AFTER 8 CHARACTERS IN THE FILENAME ; AFTR8: LD A,(HL) ;GET NEXT CHAR CP 0DH ;OK IF RET Z CP '.' ;OK IF '.' INC HL ;PT TO NEXT AFTER '.' RET Z JR AFTR8 ; ; BLANK FILL FOR THE REMAINDER OF THE NAME ; BLANK: LD A,' ' ;GET LD (DE),A ;PUT IT INC DE ;PT TO NEXT DJNZ BLANK ;COUNT DOWN RET ; ;COMMAND: A ; BUILD ASCII STRINGS USING DB'S ; ASCASM: LD A,1 ;SET FLAG LD (ASCBLD),A XOR A ;TURN OFF BUILD BY B COMMAND LD (BUILD),A JR LIST1 ;PERFORM LIST ; ;COMMAND: B ; BUILD LABELS ; BLDASM: LD A,1 ;TURN ON BUILD BY B COMMAND LD (BUILD),A XOR A ;TURN OFF BUILD BY A COMMAND LD (ASCBLD),A JR LIST1 ; ;COMMAND: L ; DISASSEMBLE WITH THE 'L' OPTION ; LIST: XOR A ;TURN OFF A AND B FLAGS LD (BUILD),A LD (ASCBLD),A LIST1: XOR A ;DISABLE OUTPUT TO DISK LD (WRTENAB),A LD A,(NLINES) ;SET LINE COUNT LD (LCTR),A LD (CNTENAB),A ;ENABLE LINE COUNT LD HL,INBUF+3 ;PT TO CHAR AFTER L, A, OR B COMMAND LD A,(HL) ;GET IT CP 0DH ;DO DEFAULT NUMBER IF EOL JR Z,TENL CP ',' ;USE CURRENT POSITION FOR FIRST ARG IF ',' JR Z,LIST3 CP ' ' ;SAME AS ',' JR Z,LIST3 CP '=' ;SET DEFAULT NUMBER OF LINES IF '=' JR NZ,LIST2 ; ; SET DEFAULT NUMBER OF LINES FOR LIST ; NWLNCT: INC HL ;PT TO ARG CALL CNVRT ;GET IT IN DE LD A,E ;ERROR IF ZERO OR A JP Z,WHAT LD (NLINES),A ;SET COUNTS LD (LCTR),A LD A,(HL) ;GET NEXT CHAR INC HL CP ',' ;CONTINUE IF COMMA OR SPACE JR Z,LIST2 CP ' ' JR Z,LIST2 CP 0DH ;DONE IF JP Z,GETCMD JP WHAT ;ERROR OTHERWISE ; ; GET FIRST ARG FOR L, A, OR B FROM COMMAND LINE ; LIST2: CALL CNVRT ;GET VALUE IN DE EX DE,HL LD (PC),HL ;SET PC TO IT EX DE,HL CP 0DH ;DONE? JR Z,TENL ;DO DEFAULT NUMBER IF SO CP ' ' ;GET 2ND ARG IF JR Z,LIST3 CP ',' ;SAME IF ',' JP NZ,WHAT ;ERROR OTHERWISE ; ; GET 2ND ARG FOR L, A, OR B COMMAND ; LIST3: INC HL ;PT TO FIRST CHAR OF 2ND ARG CALL CNVRT ;GET ITS VALUE IN DE EX DE,HL LD (ENDLST),HL ;SET END OF LISTING TO IT XOR A ;TURN OFF LINE COUNTING LD (CNTENAB),A ; ; MAIN PROCESSING LOOP FOR L, A, AND B COMMANDS ; TENL: CALL BRKCHK ;CHECK FOR BREAK LD A,(CNTENAB) ;CHECK FOR LINE COUNTING IN PROGRESS OR A ;0 = NO JR Z,CONTL ;CONTINUE IF NOT LD A,(LCTR) ;GET COUNT DEC A ;COUNT DOWN JP M,GETCMD ;RETURN TO COMMAND PROCESSING IF DONE JR FLAGA ; ; COMPARE ENDLST WITH PC ; CONTL: LD HL,(ENDLST) ;DONE WITH DISPLAY? LD A,(PC) SUB L LD A,(PC+1) SBC A,H JP NC,GETCMD ; ; CHECK FOR A OR B COMMANDS ; FLAGA: LD A,(ASCBLD) ;A COMMAND IF ASCBLD NOT ZERO OR A JR Z,MOREL ; ; THIS IS THE MAJOR FUNCTION TO BUILD ASCII DB'S ; BUILDA: LD HL,(PC) ;HL PTS TO NEXT BYTE (RELATIVE) EX DE,HL ;PTR IN DE LD HL,(OFFSET) ;HL CONTAINS OFFSET ADD HL,DE ;HL PTS TO NEXT BYTE ABSOLUTE LD B,8 ;LOOK FOR 8 ASCII CHARS IN A ROW LOOP8: LD A,(HL) ;CHECK FOR ASCII CHAR CALL ISITASC ;IS IT ASCII? JR C,MOREL ;NO, SKIP TO NEXT BYTE INC HL ;YES, PT TO NEXT DJNZ LOOP8 ; ; FIND END OF THIS ASCII STRING ; FOLLOW: LD A,(HL) ;LOOK UNTIL NON-ASCII INC HL ;PT TO NEXT CALL ISITASC JR NC,FOLLOW DEC HL ;PT TO NON-ASCII CHAR CALL TWOS ;SUBTRACT OFFSET FROM LOCATION EX DE,HL ;RESULT IN DE PUSH DE ;SAVE PTR TO BYTE AFTER DB STRING FOR 'I' CONTROL LD HL,(PC) ;GET VALUE OF BEGINNING OF ASCII STRING EX DE,HL ;... IN DE LD A,'B' ;SET B CONTROL POINT CALL FTCTL0 ;A='B', DE=ADDRESS POP HL LD (PC),HL ;SET NEW ADDRESS TO CONTINUE FROM EX DE,HL LD A,'I' ;A='I', DE=ADDRESS FOR INSTR CONTROL CALL FTCTL0 ; ; NOW LOOK FOR ANY COMMENTS AT THIS ADDRESS ; MOREL: LD HL,(COMST) ;COMMENT TABLE IN USE? LD A,H ;ADDRESS IS ZERO IF NOT OR L JR Z,NCMT LD HL,(PC) ;HL PTS TO PC EX DE,HL ;DE PTS TO PC CALL CMCHK ;CHECK COMMENT TABLE FOR MATCH JR C,NCMT ;NO MATCH INC HL ;PT TO CHAR COUNT OF COMMENT INC HL LD B,(HL) ;B=NUMBER OF CHARS IN COMMENT INC HL ;PT TO FIRST CHARACTER LD A,(HL) ;A=FIRST CHAR OF COMMENT CP ';' ;A ';' COMMENT IS LISTED AFTER THE OPCODE DEC HL ;PT BACK TO CHAR COUNT JR NZ,MOREL1 ;CONTINUE IF NO ';' LD (XCPTR),HL ;SAVE THE COMMENT ADDRESS JR NCMT ; ; THIS ROUTINE WILL ; PRINT COMMENTS ; LIKE THIS ; NWLN: SCF NWLN0: LD A,1 ;ENABLE WRITING LD (WRTENAB),A CALL C,SEMI ;OUTPUT SEMI BEFORE NEW COMMENT XOR A OR B ;CHECK CHAR COUNT FOR DONE RET Z ;DONE IF ZERO CHARS LEFT CNTCMT: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CP '\' ;NEW LINE? JR NZ,NTBKSL CALL CRLF ;NEW LINE DEC B ;DEC CHAR COUNT JR NWLN ;CONT NTBKSL: CALL COUT ;PRINT CHAR DEC B ;DECREMENT COUNT JR NZ,CNTCMT RET MOREL1: CP '*' ; A '*' COMMENT REPLACES THE ENTIRE LINE JR NZ,MOREL2 LD (RPLPTR),HL JR NCMT ; ; PRINT COMMENT PTED TO BY HL AND THEN NEW LINE ; MOREL2: CALL NWLN ;PRINT COMMENT CALL CRLF ; ; NOW PROCESS THE BYTE AS AN INSTRUCTION IF IT IS ; NCMT: LD HL,(PC) ;PT TO PC EX DE,HL ;... IN DE CALL SCHCTL ;CHECK CONTROL TABLE DEC HL ;PT TO CONTROL MODE OF PREVIOUS ENTRY JR C,RDCTL ;IF NO MATCH, CONTROL MODE OF PREVIOUS ENTRY IS IT INC HL ;SINCE MATCH, PT TO CONTROL MODE OF MATCHED ENTRY INC HL INC HL ; ; CHECK CONTROL MODE ; RDCTL: LD A,(HL) ;GET CONTROL MODE CP 'I' ;IS IT INSTRUCTION? JR Z,ICTL ;PROCESS IF SO CP 'E' ;END OF PROGRAM? JP Z,CLOSE ;DONE IF SO PUSH AF ;ELSE SAVE CONTROL MODE INC HL ;PT TO ADDRESS OF NEXT CONTROL MODE LD E,(HL) ;ADDRESS IN DE INC HL LD D,(HL) PUSH DE ;SAVE ADDRESS OF NEXT CONTROL ENTRY LD HL,(PC) ;PT TO PC EX DE,HL ;... IN DE CALL HSYM ;PRINT SYMBOL IF THERE POP HL ;HL IS ADDRESS OF NEXT CONTROL ENTRY LD (NXTCTL),HL ;SAVE IT EX DE,HL ;... IN DE ALSO XOR A ;DISABLE WRITE LD (WRTENAB),A POP AF ;GET CONTROL MODE CP 'S' ;DS? JP Z,DSMODE CP 'B' ;DB? JP Z,BMODE CP 'H' ;DB HEX? JP Z,HMODE CP 'W' ;DW? JP Z,WMODE CALL COUT ;ELSE PRINT AS ERROR CALL PSTRNG DEFB ': Invalid CTL Entry',0DH,0AH,0 JP GETCMD ; ; EXECUTE HERE IF THE 'I' CTL IS IN EFFECT -- INTERPRET AS INSTRUCTION ; DE PTS TO BYTE WHICH IS BEING PROCESSED ; ICTL: CALL DASM ;INVOKE DISASSEMBLER XOR A ;DISABLE WRITE LD (WRTENAB),A JP TENL ; ; DS CTL -- DE CONTAIN NEXT CTL ADDRESS ; DSMODE: PUSH DE ;SAVE NEXT CONTROL LD A,(PC) ;COMPUTE -PC IN HL CPL LD L,A LD A,(PC+1) CPL LD H,A INC HL ADD HL,DE ;HL = LENGTH OF SPACE DEFINED LD A,1 ;ENABLE WRITING LD (WRTENAB),A CALL PSTG ;PRINT 'DS' DEFB 'DS',9,0 LD A,H ;PRINT SIZE OF AREA CALL PASHEX LD A,L CALL PHEX LD A,'H' CALL COUT CALL CRLF POP HL ;GET PTR TO NEXT CONTROL ENTRY LD (PC),HL ;SET PC TO IT JP TENL ;CONTINUE ; ; DW CTL -- PROCESS DW AND LOOK FOR LABELS ; WMODE: LD A,1 ;ENABLE WRITING LD (WRTENAB),A CALL PSTG ;PRINT 'DW' DEFB 'DW',9,0 LD HL,(PC) ;GET PC EX DE,HL ;... IN DE LD HL,(OFFSET) ;GET OFFSET ADD HL,DE ;HL PTS TO ACTUAL BYTE PAIR LD E,(HL) ;SET DE TO DW VALUE INC HL LD D,(HL) CALL PRNTDE ;PRINT DW VALUE CALL CRLF LD HL,(PC) ;ADVANCE PC TO BYTE AFTER DW VALUE INC HL INC HL LD (PC),HL JP TENL ;CONTINUE PROCESSING ; ; NEW LINE AND CONTINUE ; STPLN: CALL CRLF JP TENL ; ; DB HEX MODE -- BUILD HEX DB'S ; HMODE: XOR A ;SET FLAG LD (ADB),A JR BMODE1 ; ; DB MODE -- BUILD ASCII STRINGS LONGER THAN 8 CHARACTERS ; BMODE: LD A,0FFH ;SET FLAG FOR ASCII LD (ADB),A BMODE1: XOR A ;INIT LENGTH TO ZERO LD (BLNGTH),A INC A ;ENABLE WRITING LD (WRTENAB),A CALL PSTG ;PRINT 'DB' DEFB 'DB',9,0 ; ; PROCESS BYTES OF DB ; MOREB: LD HL,(PC) ;GET RELATIVE ADDRESS EX DE,HL ;... IN DE LD HL,(OFFSET) ;GET OFFSET ADD HL,DE ;PT TO ACTUAL BYTE LD A,(ADB) ;CHECK FOR ASCII BUILD OR A ;0=NO LD A,(HL) ;GET BYTE OF DB JR Z,LTSPC ;XXH BUILD CP 0AH ;? JR C,LTLF ;PROCESS IF LESS THAN CP ' ' ; JR C,LTSPC ;PROCESS IF LESS THAN CP 7FH ;? JP C,LTRUB ;PROCESS IF GREATER THAN ; ; PRINT BYTE AS HEX NUMBER ; LTSPC: CALL PASHEX ;PRINT BYTE IN A AS HEX LD A,'H' CALL COUT LD A,(BLNGTH) ;INCREASE LENGTH BY 2 ADD A,2 LD (BLNGTH),A JR MVUP ; ; CHAR IS LESS THAN -- MAKE IT SINGLE DIGIT (LIKE 9 FOR TAB) ; LTLF: OR '0' ;MASK FOR ASCII CALL COUT ;PRINT DIGIT ; ; ADVANCE TO NEXT BYTE ; MVUP: INC HL ;PT TO NEXT BYTE EX DE,HL ;... IN DE LD HL,(PC) ;PT TO PC INC HL ;ADVANCE PC LD (PC),HL EX DE,HL ;DE PTS TO PC, HL PTS TO NEXT BYTE ; ; CHECK TO SEE IF THE NEXT CONTROL POINT BEEN REACHED ; CNXCTL: LD A,(NXTCTL) ;COMPARE AGAINST PC CP E JR NZ,TRYSYM LD A,(NXTCTL+1) CP D JP Z,QTB ; ; SEE IF WE ARE POINTING TO A SYMBOL'S ADDRESS ; TRYSYM: LD HL,(PC) ;PC IN DE EX DE,HL CALL SYMSCH ;LOOK FOR SYMBOL JP NC,STPLN ;NEW LINE IF THERE IS A SYMBOL LD A,(BLNGTH) ;INCREASE LINE BY 2 ADD A,2 LD (BLNGTH),A CP 27 JP NC,STPLN ;NEW LINE IF STRING EXCEEDS 27 CHARS LD A,',' ;SEPARATE BY COMMA OTHERWISE CALL COUT JP MOREB ; ; VALID CHAR ... BEGIN PROCESSING AS QUOTED STRING ; LTRUB: LD A,'''' ;OUTPUT QUOTE CALL COUT LD A,(BLNGTH) ;INC LENGTH INC A LD (BLNGTH),A LD A,(HL) ;GET CHAR ; ; OUTPUT AS ASCII CHARS ; MORASC: CALL COUT ;PRINT CHAR LD A,(HL) ;CHECK FOR QUOTE CP '''' ;COMPARE CALL Z,COUT ;DOUBLE QUOTE INC HL ;PT TO NEXT CHAR EX DE,HL ;... IN DE LD HL,(PC) ;INCR PC INC HL LD (PC),HL EX DE,HL ;DE=NEXT PC LD A,(NXTCTL) ;CHECK FOR CONTROL CP E JR NZ,YET LD A,(NXTCTL+1) CP D JR Z,FNLQT ; ; CHECK FOR SYMBOL HERE ; YET: PUSH HL LD HL,(PC) EX DE,HL CALL SYMSCH POP HL JR NC,FNLQT ;OUTPUT ENDING QUOTE AND NEW LINE FOR SYMBOL LD A,(BLNGTH) ; BREAK INC A ;INCR LINE LENGTH ; ; KEEP THE LINES LESS THAN 27 LONG ; LD (BLNGTH),A CP 35 JR NC,LASTQT CP 27 JR C,STILL ; ; OVER 17H CHARACTERS HAVE BEEN QUOTED ; DEC HL LD A,(HL) INC HL CP ' ' JR Z,FNLQT STILL: LD A,(HL) CP ' ' JR C,LASTQT CP 7FH JP C,MORASC ; ; PRINT A TRAILING QUOTE ; LASTQT: LD A,'''' ;PRINT QUOTE CALL COUT JP CNXCTL ; ; PRINT ENDING QUOTE AND NEW LINE ; FNLQT: LD A,'''' CALL COUT QTB: CALL CRLF JP TENL ; ;COMMAND: I
, ; INCREMENT SYMBOL TABLE ADDRESSES AFTER AND ON
BY ; FOR DISASSEMBLY OF NEW VERSIONS OF PROGRAMS ; INCMNT: LD HL,INBUF+3 ;LOOK AT COMMAND LINE LD A,(HL) ;GET CHAR AFTER 'I' CP 0DH ;ERROR IF EOL JP Z,WHAT CALL CNVRT ;GET FIRST VALUE IN DE PUSH DE ;SAVE STARTING ADDRESS ON STACK CP ' ' ;CHECK FOR VALID DELIMITER JR Z,INCM1 CP ',' ;' ' OR ',' DELIMITER JP NZ,WHAT INCM1: INC HL ;PT TO FIRST CHAR AFTER DELIMITER CALL CNVRT ;GET OFFSET IN DE CP 0DH ;MUST BE EOL NOW JP NZ,WHAT LD B,D ;BC=OFFSET LD C,E POP DE ;DE=START ADDRESS LD HL,SYMTAB ;PT TO TABLE ; MAJOR LOOP FOR SCANNING SYMBOL TABLE -- HL PTS TO LOW SYM ADDRESS BYTE INCM2: INC HL ;PT TO HI SYM ADDRESS LD A,(HL) ;GET HI DEC HL ;PT TO LOW SYM ADDRESS CP D ;COMPARE JR C,INCM4 ;SKIP SYMBOL ENTRY JR NZ,INCM3 ;SYMBOL IS GREATER SO ADD OFFSET TO IT LD A,(HL) ;GET LOW CP E ;COMPARE JR C,INCM4 ;SKIP SYMBOL ENTRY ; ADD OFFSET TO SYMBOL ADDRESS PTED TO BY HL INCM3: LD A,(HL) ;GET LOW ADDRESS BYTE ADD A,C ;ADD LOW OFFSET BYTE LD (HL),A ;PUT LOW ADDRESS BYTE INC HL ;PT TO HI ADDRESS BYTE LD A,(HL) ;GET HIGH ADDRESS BYTE ADC A,B ;ADD HI OFFSET BYTE LD (HL),A ;PUT HI ADDRESS BYTE DEC HL ;PT TO LOW ADDRESS BYTE ; SKIP TO NEXT SYMBOL -- HL PTS TO LOW ADDRESS BYTE INCM4: INC HL ;PT TO HI ADDRESS INC HL ;PT TO CHAR COUNT LD A,(HL) ;GET CHAR COUNT OR A ;DONE IF ZERO JP Z,GETCMD INC HL ;PT TO FIRST CHAR OF SYMBOL ADD A,L ;ADD SYMBOL LENGTH TO HL LD L,A LD A,0 ;ADD IN HI NOW ADC A,H LD H,A ;HL PTS TO FIRST BYTE OF NEXT SYMBOL JR INCM2 ;CONTINUE PROCESSING ; ;COMMAND: ? ; STATISTIC OUTPUT ; STAT: CALL PSTRNG ;THIS IS RATHER STRAIGHT-FORWARD, SO FEW COMMENTS DEFB 'Scratch Area Start = ',0 LD HL,ENDALL CALL PVALUE ;PRINT VALUE CALL PSTRNG DEFB 0DH,0AH DEFB 'Scratch Area End = ',0 LD HL,(6) LD L,0 CALL PVALUE ;print the beginning of BDOS (not CCP) CALL PSTRNG DEFB 0DH,0AH,0AH DEFB 'COM Start = 0100',0dh,0ah DEFB 'COM End = ',0 LD HL,(RELEND) ;GET END ADDRESS CALL PVALUE CALL PSTRNG DEFB 0DH,0AH,0AH DEFB 'SYMTBL = ',0 LD HL,SYMTAB CALL PVALUE LD HL,(SYMEND) CALL PVALUE CALL CRLF CALL PSTRNG DEFB 'PC = ',0 LD HL,(PC) CALL PVALUE CALL CRLF CALL PSTRNG DEFB 'OFFSET = ',0 LD HL,(OFFSET) CALL PVALUE CALL CRLF LD HL,(COMST) LD A,H OR L JR Z,CTLSTT CALL PSTRNG DEFB 'COMNTS = ',0 LD HL,(COMST) CALL PVALUE LD HL,(COMEND) CALL PVALUE CALL CRLF CTLSTT: CALL CTLST CALL CMNTST JP GETCMD ; ; PRINT PARAMETERS OF CONTROL TABLE ; CTLST: CALL PSTRNG ;PRINT THE START AND END OF CONTROL TABLE DEFB 'CTLTBL = ',0 LD HL,CTLTBL CALL PVALUE ; ; FIND THE END OF THE CTLTBL (FF,FF) ; FNDEND: LD A,(HL) ;GET FIRST BYTE INC HL ;PT TO NEXT AND (HL) ;AND IT IN ... IF BOTH ARE 0FFH, RESULT IS 0FFH INC HL ;PT TO CTL LETTER INC HL ;PT TO NEXT BYTE OF ADDRESS INC A ;IF RESULT WAS 0FFH, A NOW EQUALS 0 JR NZ,FNDEND ;CONTINUE UNTIL A=0 DEC HL ;BACK UP TO PREVIOUS ENTRY (END OF TABLE) DEC HL DEC HL CALL PVALUE ;PRINT THE VALUE 0FFFFH JP CRLF ; ; PRINT THE STATUS MESSAGE OF THE SYMBOL COMMENTS FACILITY ; CMNTST: CALL PSTRNG ;PRINT THE STATUS OF SYMBOL COMMENTS DEFB 'Symbol Comments are O',0 LD A,(XCSW) OR A LD A,'N' JR NZ,CMTST1 LD A,'F' CALL COUT CMTST1: CALL COUT JP CRLF ; ;COMMAND: F ; FIND THE OCCURRENCE OF ADDRESSES ; FIND: LD HL,INBUF+3 LD A,(HL) CP 0DH ;CHECK FOR NO FURTHER ARGS JR Z,PREVF CALL CNVRT ;GET ARG IN DE EX DE,HL ; ... IN HL LD (FNDADD),HL ;ADDRESS TO LOOK FOR LD HL,(OFFSET) ;GET OFFSET LD (FNDPC),HL ;SET START OF SEARCH ADDRESS EX DE,HL ;RESTORE HL TO PT TO CHAR IN COMMAND LINE CP 0DH ;DONE? JR Z,PREVF CP ' ' ; OR ',' MEAN TO CONTINUE JR Z,FIND0 CP ',' JP NZ,WHAT FIND0: INC HL CALL CNVRT ;GET 2ND ARG FOR FIND CP 0DH JP NZ,WHAT LD HL,(OFFSET) ;SET THIS AS STARTING ADDRESS ADD HL,DE ;WITH PROPER OFFSET LD (FNDPC),HL ;START LOOKING FROM HERE ; ; CONTINUE THE PREVIOUS 'F' COMMAND ; PREVF: LD HL,(FNDADD) ;GET ADDRESS WE ARE LOOKING FOR EX DE,HL ;... IN DE NYET: CALL BRKCHK ;CHECK FOR BREAK LD HL,(FNDPC) ;PT TO PC LD A,(HL) ;GET BYTE AT PC INC HL ;PT TO NEXT LD (FNDPC),HL CP E ;COMPARE BYTE WITH ADDRESS WE ARE LOOKING FOR JR NZ,NYET LD A,(HL) ;PARTIAL MATCH -- TRY HIGH BYTE CP D JR NZ,NYET ; ; WE FOUND ADDRESS IN MEMORY -- PRINT DATA ; PUSH HL PUSH DE CALL TWOS DEC HL CALL PVALUE ;PRINT LOCATION OF FOUND ADDRESS (RELATIVE) POP DE POP HL CALL SPACE ;PRINT JR NYET ; ; HL=HL-OFFSET ; TAKE 2'S COMPLEMENT OF OFFSET AND ADD TO H & L. ; TWOS: LD A,(OFFSET) ;GET 2'S COMP OF OFFSET IN DE CPL LD E,A LD A,(OFFSET+1) CPL LD D,A INC DE ADD HL,DE ;HL=HL+DE RET ; ;COMMAND: Z ; CLOSE THE FILE ; CLOSE: CALL HSYM LD A,1 ;ENABLE WRITING TO DISK FILE LD (WRTENAB),A CALL PSTG ;WRITE END STATEMENT DEFB 'END',0DH,0AH,0 XOR A ;DISABLE WRITING TO FILE LD (WRTENAB),A LD A,(FOPEN) ;CHECK IF FILE WAS OPEN OR A JP Z,GETCMD LD A,1AH ;FILL WITH ^Z CALL WRTFILE CALL NXTRCRD XOR A ;CLOSE FILE LD (FOPEN),A CALL PSTRNG ;PRINT MESSAGE DEFB '++ ASM File Closed ++',0DH,0AH,0 JP GETCMD ; ;COMMAND: R ; READ A FILE OR FILES ; READ: CALL SETFCB ;LOAD THE FCB WITH THE PROPER FILE NAME AND TYPE LD A,(FOPEN) ;CHECK TO SEE IF A FILE IS ALREADY OPENED OR A JP NZ,CANT ;ABORT IF SO LD HL,FCBTYPE ;CHECK FILE TYPE LD DE,TPALL ;IS IT 'ALL'? LD C,3 CALL CHKSTG JP NZ,NOTALL ;PROCEED IF NOT ; ; READ IN DOC, SYM, CTL FILES ; CALL ALLRD ;READ IN ALL FILES JP STAT ;PRINT STATISTICS ; ; READ IN ALL FILES -- COMMON ROUTINE ; ALLRD: LD HL,TPDOC ;SET FILE TYPE TO DOC CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 0dh,0ah DEFB 'Reading DOC file...',0dh,0ah,0 CALL DOCRD ;READ FILE IN LD HL,TPSYM ;SET FILE TYPE TO SYM CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 'Reading SYM file...',0dh,0ah,0 CALL SYMRD ;READ FILE IN LD HL,TPCTL ;SET FILE TYPE TO CTL CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 'Reading CTL file...',0dh,0ah,0 CALL CTLRD ;READ FILE IN IF RDCOMQ ;ENABLE QUESTION OF COM FILE READ? CALL PSTRNG DEFB 'Read in COM File (Y/N)? ',0 CALL CHIN ;GET RESPONSE CP 'Y' JP NZ,STAT ;PRINT STATISTICS ENDIF LD HL,TPCOM ;SET FILE TYPE TO COM CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 'Reading COM file...',0dh,0ah,0 CALL COMRD ;READ FILE IN RET ; ; SET THE FILE TYPE TO THAT PTED TO BY HL ; FIXTYP: LD DE,FCBTYPE LD B,3 XOR A LD (FCB+0CH),A ;zero the extent byte JP SLIDE ; ; FILE TYPE WAS NOT 'ALL', SO CHECK TO SEE WHAT TYPE IT WAS AND PROCESS ; NOTALL: LD HL,FCBTYPE ;CHECK FOR SYM LD DE,TPSYM LD C,3 CALL CHKSTG JR NZ,NOTSYM CALL SYMRD ;READ SYM FILE JP STAT ;PRINT STATS NOTSYM: LD HL,FCBTYPE ;CHECK FOR COM LD DE,TPCOM LD C,3 CALL CHKSTG JP NZ,NOTCOM CALL COMRD ;READ IN A COM FILE JP GETCMD ;CONTINUE COMMAND LINE PROCESSING ; ; READ IN COM FILE ; COMRD: CALL RDOPEN ;OPEN COM FILE FOR READ LD HL,(OFFSET) ;HL=OFFSET LD A,H CP (SYMTAB+600H) SHR 8 ;CHECK FOR NO OVERWRITE OF SYMTABLE JP C,OSERR LD DE,0100H ;SET DMA ADDRESS TO OFFSET PLUS 100H ADD HL,DE SETDMA: PUSH HL ;SET THE DMA ADDRESS. EX DE,HL LD C,1AH CALL BDOS LD DE,FCB ;READ A RECORD. LD C,14H CALL BDOS OR A ;DONE? JR NZ,RDCMPLT POP HL LD DE,RECLEN ;PT TO NEXT BLOCK FOR READ ADD HL,DE JP SETDMA ;CONTINUE ; ; DONE WITH LOAD OF COM FILE ; RDCMPLT: POP HL ;GET DMA ADDRESS OF LAST READ CALL PSTRNG DEFB 'Last Block Read into Memory at ',0 CALL PVALUE CALL PSTRNG DEFB 0DH,0AH DEFB 'Last Block Ends at Relative ',0 CALL TWOS LD (RELEND),HL ;SAVE RELATIVE END ADDRESS CALL PVALUE CALL CRLF LD DE,RECLEN ;RESET THE DMA ADDRESS TO 80H LD C,1AH CALL BDOS RET ; ; THE READ IS NOT A .SYM OR A .COM FILE ; NOTCOM: LD HL,FCBTYPE ;CHECK FOR CTL FILE LD DE,TPCTL LD C,3 CALL CHKSTG JR NZ,NOTCTL JP ISCTL ;READ IN CTL FILE NOTCTL: LD HL,FCBTYPE ;CHECK FOR DOC FILE LD DE,TPDOC LD C,3 CALL CHKSTG JP NZ,WHAT ;ERROR IF NOT COM, SYM, CTL, OR DOC CALL DOCRD ;READ IN DOC FILE JP STAT ; ; ERROR -- ATTEMPT TO OVERLAY THE SYMBOL TABLE OR DISASSEMBLER ; OSERR: CALL PSTRNG DEFB '++ NO, that would overlay ' DEFB 'the Disassembler',0DH,0AH DEFB 'because the Offset is too small: ' DEFB 0 CALL PRNTOS CALL PSTRNG DEFB ' ++',0DH,0AH,0 RET ; ; READ THE SYMBOL TABLE FROM DISK ; SYMRD: LD HL,SYMTAB ;PT TO SYMBOL TABLE CALL READFILE ;READ FILE INTO IT LD (SYMEND),HL ;SET END ADDRESS OF SYMBOL TABL INC HL ;PT TO NEXT SYMBOL CHAR COUNT INC HL LD (HL),0 ;SET CHAR COUNT TO ZERO RET ; ; READ THE DOC (COMMENTS) FILE FROM DISK ; DOCRD: CALL AREACK ;MAKE SURE COMMENTS AREA DEFINED LD HL,(COMST) ;PT TO START OF COMMENTS AREA CALL READFILE ;READ FILE IN LD (COMEND),HL ;SET END OF COMMENTS AREA LD (HL),0FFH ;STORE 0FFFFH AS ADDRESS OF NEXT COMMENT INC HL LD (HL),0FFH RET ; ; READ FILE SET IN FCB INTO MEMORY PTED TO BY HL ; READFILE: CALL RDOPEN ;OPEN FILE RDFL1: CALL READMA ;READ NEXT BYTE (RETURNED IN A) CP 1AH ;RETURN IF EOF EACHED RET Z CP 9 ;IGNORE , , JR Z,RDFL1 CP 0DH JR Z,RDFL1 CP 0AH JR Z,RDFL1 CALL NUM1 ;CONVERT FROM HEX CHARS TO VALUE IN DE LD (HL),E ;SAVE THE ADDRESS INC HL LD (HL),D INC HL PUSH HL INC HL LD B,0 ;COUNT CHARS IN SYMBOL SYMLUP: CALL READMA ;GET NEXT BYTE CP 9 ;DONE IF OR JR Z,SYMTERM CP 0DH JR Z,SYMTERM LD (HL),A ;STORE BYTE INC HL ;PT TO NEXT INC B ;INCR CHAR COUNT JR SYMLUP SYMTERM: EX (SP),HL LD (HL),B POP HL JP RDFL1 ; ; READ NUMBER FROM DISK FILE (1ST HEX DIGIT IN A ON ENTRY) ; VALUE RETURNED IN DE ; NUM1: LD DE,0 ;INIT NUMBER TO ZERO LUP1: CP ' ' ;DONE IF RET Z CP 1AH ;ERROR IF EOF JP Z,ERROR1 CP '9'+1 ;WITHIN DIGIT RANGE? JR C,NUMER1 ;IS A DIGIT SUB 7 ;CONVERT 'A' TO 'F' TO '9'+1 TO 'E'+1 NUMER1: SUB '0' ;CONVERT TO BINARY IN A EX DE,HL ;OLD VALUE IN HL ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 ADD A,L ;+A LD L,A ;ONLY CHANGES LOW-ORDER BYTE EX DE,HL ;VALUE BACK IN DE CALL READMA CP 1AH JP Z,ERROR1 JR LUP1 ; ;COMMAND: S ; SAVE THE FILES ; SAVE: CALL SETFCB ;LOAD THE FCB FROM THE COMMAND LINE LD A,(FOPEN) ;CHECK FOR FILE ALREADY OPEN OR A ;ABORT IF SO JP NZ,CANT LD HL,FCBTYPE ;CHECK FOR TYPE OF 'ALL' LD DE,TPALL LD C,3 CALL CHKSTG JP NZ,NTALL ;CHECK FOR SPECIFIC TYPE IF NOT ALL LD HL,TPDOC ;SAVE DOC FILE CALL FIXTYP CALL PSTRNG DEFB 0dh,0ah DEFB 'Saving .DOC file...',0dh,0ah,0 CALL DOCSV LD HL,TPSYM ;SAVE SYM FILE CALL FIXTYP CALL PSTRNG DEFB 'Saving .SYM file...',0dh,0ah,00 CALL SYMSV LD HL,TPCTL ;SAVE CTL FILE CALL FIXTYP CALL PSTRNG DEFB 'Saving .CTL file...',0dh,0ah,0 CALL SVCTL0 CALL PSTRNG ;OPTIONALLY SAVE ASM FILE DEFB 'Create a New .ASM File (Y/N)? ',0 CALL CHIN ;GET CHAR CP 'Y' JP NZ,GETCMD LD HL,TPASM ;SAVE ASM FILE CALL FIXTYP ; ; SAVE THE ASM FILE ; SVASM: LD A,1 ;MARK FILE AS OPEN LD (FOPEN),A XOR A ;DISABLE WRITING AT THIS TIME LD (WRTENAB),A CALL OPEN ;OPEN FILE FOR OUTPUT CALL PSTRNG ;PRINT MESSAGE DEFB '++ Writing ASM Enabled' DEFB 0DH,0AH,'Use Z Command or ' DEFB 'E Control to Close File ++' DEFB 0DH,0AH,0 JP GETCMD ;NOW PROCESS USER'S NEXT COMMANDS ; ; TYPE WAS NOT ALL, SO CHECK FOR SPECIFIC FILE TYPES ; NTALL: LD HL,FCBTYPE ;CHECK FOR SYM LD DE,TPSYM LD C,3 CALL CHKSTG JP NZ,NTSYM CALL SYMSV JP GETCMD ; ; ROUTINE TO SAVE THE SYMBOL TABLE ; SYMSV: LD HL,SYMTAB ;PT TO SYMBOL TABLE SVFL: CALL OPEN ;OPEN THE FILE LUP2: LD E,(HL) ;GET ADDRESS OF SYMBOL IN DE INC HL LD D,(HL) INC HL LD A,(HL) ;GET LENGTH OF SYMBOL IN A INC HL LD B,A ;... AND B OR A ;DONE IF LENGTH IS ZERO JP Z,WRTEOF ;WRITE EOF TO FILE IF DONE CALL EXPND ;WRITE ADDRESS IN DE AS ASCII CHARS ON DISK LD A,' ' ;OUTPUT CALL WRTFILE WRTSYM: LD A,(HL) ;GET NEXT CHAR OF SYMBOL CALL WRTFILE ;WRITE TO DISK INC HL ;PT TO NEXT DJNZ WRTSYM ;COUNT DOWN SIZE OF SYMBOL LD A,0DH ;WRITE NEW LINE CHARS CALL WRTFILE LD A,0AH CALL WRTFILE JR LUP2 ; ; WRITE AN EOF ; WRTEOF: LD A,1AH ;WRITE EOF CALL WRTFILE CALL NXTRCRD RET ; ; EXPAND AN ADDRESS IN DE TO ASCII CHARS AND SAVE ON DISK ; EXPND: LD A,D ;OUTPUT HIGH NYBBLE OF HIGH-ORDER BYTE CALL HINIB ;ROUTINE TO DO THIS CALL WRTFILE ;WRITE ASCII CHAR IN A TO DISK LD A,D ;OUTPUT LOW NYBBLE CALL LONIB CALL WRTFILE LD A,E ;HIGH OF LOW-ORDER BYTE CALL HINIB CALL WRTFILE LD A,E ;LOW OF LOW-ORDER BYTE CALL LONIB JP WRTFILE ; ; NOT OF TYPE SYM -- CHECK FOR CTL ; NTSYM: LD HL,FCBTYPE ;CHECK FOR CTL TYPE LD DE,TPCTL LD C,3 CALL CHKSTG JP Z,SVCTL ;YES, SO SAVE CTL FILE LD HL,FCBTYPE ;CHECK FOR DOC TYPE LD DE,TPDOC LD C,3 CALL CHKSTG JR Z,SVDOC ;YES, SO SAVE DOC FILE LD HL,FCBTYPE ;CHECK FOR ASM TYPE LD DE,TPASM LD C,3 CALL CHKSTG JP NZ,WHAT ;ERROR IF NOT ASM AT THIS POINT JP SVASM ;SAVE ASSEMBLY LANGUAGE (TYPE ALREADY ASM) ; ; SAVE THE COMMENT TABLE ; SVDOC: CALL DOCSV JP GETCMD ; ; SAVE COMMENTS ; DOCSV: CALL AREACK ;FIND END OF COMMENTS LD HL,(COMEND) ;GET PTR IN HL INC HL INC HL LD (HL),0 ;SET NULL FINAL COMMENT LD HL,(COMST) ;PT TO START OF TABLE JP SVFL ;PERFORM STRAIGHT SAVE ; ; ATTEMPT TO OPEN ANOTHER FILE WHILE ASM FILE ALREADY OPENED ; CANT: CALL PSTRNG DEFB '++ No File Accessed Permitted ' DEFB 'until ASM Closed ++',0DH,0AH DEFB 0 JP GETCMD ; ; EOF ENCOUNTERED TOO SOON ; ERROR1: CALL PSTRNG DEFB '++ Unexpected EOF ++',0DH,0AH DEFB 0 JP GETCMD ; ;COMMAND: C ; CONTROL TABLE ENTRIES ARE MADE HERE ; CTL: CALL IECNT ;INIT ECNT LD HL,INBUF+3 LD A,(HL) CP 0DH ;DUMP CONTROL TABLE IF JUST A 'C' COMMAND JP Z,CDUMP1 CALL CNVRT ;GET ADDRESS CP 0DH ;ERROR? JP Z,CDUMP ;DUMP IF SO CP ' ' ;DELIMITER? JR Z,CTL0 ;PROCESS 2ND OPERAND IF SO CP ',' ;SAME JP NZ,WHAT ;ERROR OTHERWISE CTL0: INC HL ;PT TO 2ND OPERAND LD A,(HL) ;GET IT (CONTROL TYPE) CALL FTCTL ;PROCESS ENTRY WITH CONTROL TABLE JP GETCMD ; ; PLACE A NEW ENTRY INTO THE CONTROL TABLE ; A=TYPE OF ENTRY (B, E, I, K, S, W) AND DE=ADDRESS ; FTCTL0: PUSH HL ;SAVE REGS PUSH DE ;NEW ADDRESS PUSH AF ;NEW TYPE CALL SCHCTL ;FIND ENTRY IN CONTROL TABLE DEC HL ;PT TO TYPE OF PREVIOUS CONTROL ENTRY JR C,FTCTL1 ;IF CARRY, WE DIDN'T MATCH INC HL ;PT TO TYPE OF CURRENT ENTRY WHICH MATCHES INC HL INC HL FTCTL1: POP AF ;GET NEW TYPE AND POP DE ;... ADDRESS CP (HL) ;DO OUR TYPES MATCH? POP HL ;RESTORE HL RET Z ;NO CHANGE IF THEY DO ; ; PLACE A NEW ENTRY INTO THE CONTROL TABLE ; FTCTL: LD (OPCTP),A ;SAVE TYPE OF ENTRY CALL SCHCTL ;SCAN FOR A MATCH JP C,PLACE ;NO MATCH, SO ENTRY MUST BE ADDED ; ; MATCH OF ADDRESS, SO SIMPLY CHANGE CONTROL MODE AT THAT POINT ; LD A,(OPCTP) ;GET TYPE OF ENTRY CP 'I' ;INSTRUCTION? JR Z,RNCTL CP 'W' ;DW? JR Z,RNCTL CP 'H' ;DB HEX? JR Z,RNCTL CP 'B' ;DB? JR Z,RNCTL CP 'S' ;DS? JR Z,RNCTL CP 'E' ;END OF PROGRAM? JR Z,RNCTL CP 'K' ;KILL SYMBOL? JR Z,DELCTL JP WHAT ;ERROR IF NONE OF THESE ; ; READ A NEW CONTROL MODE ; ENTRY FORM IS: ; DW ADDRESS ; DB CONTROL MODE ; RNCTL: INC HL ;ADDRESS IS SAME INC HL ;PT TO CONTROL MODE LD (HL),A ;ONLY SET NEW CONTROL MODE RET ; ; DELETE THE ENTRY FROM THE CONTROL TABLE ; DELCTL: EX DE,HL ;DE PTS TO ENTRY TO DELETE LD HL,3 ADD HL,DE ;HL PTS TO NEXT ENTRY EX DE,HL ;DE PTS TO NEXT ENTRY, HL PTS TO ENTRY TO DELETE ; ; COPY CONTROL TABLE DOWN ; CMPCT: LD A,(HL) ;CHECK FOR END OF CONTROL TABLE INC HL AND (HL) ;ADDRESS IS 0FFFFH IF END DEC HL INC A ;A=0 MEANS ADDRESS IS 0FFFFH JR Z,PNTHLL LD BC,3 ;NOT AT END -- COPY 3 BYTES DOWN AND CONTINUE EX DE,HL ;HL PTS TO SOURCE, DE TO DEST LDIR ;COPY THE 3 BYTES EX DE,HL ;DE PTS TO NEXT ENTRY, HL PTS TO ENTRY TO DELETE JR CMPCT ;CONTINUE COPY OPERATION ; ; COPY COMPLETE ; PNTHLL: CALL CTLST ;PRINT CONTROL TABLE INFORMATION JP GETCMD ; ; PLACE AN ENTRY INTO THE CONTROL TABLE ; ON ENTRY, HL PTS TO ENTRY TO INSERT BEFORE ; PLACE: LD A,(OPCTP) ;GET TYPE OF COMMAND CP 'K' ;ERROR IF KILL JP Z,WHAT CP 'E' ;SET END OF PROGRAM AREA JR Z,LGLCTL CP 'H' ;DB HEX JR Z,LGLCTL CP 'B' ;DB JR Z,LGLCTL CP 'W' ;DW JR Z,LGLCTL CP 'I' ;INSTRUCTION JR Z,LGLCTL CP 'S' ;DS JP NZ,WHAT ;ERROR IF NONE OF THESE ; ; PLACE ENTRY INTO CONTROL TABLE; A=TYPE, DE=ADDRESS, HL=ADDR OF ENTRY ; TO INSERT BEFORE ; LGLCTL: PUSH DE ;SAVE ADDRESS PUSH HL ;SAVE ADDRESS OF ENTRY TO INSERT BEFORE LD HL,CTLTBL ;PT TO FRONT OF TABLE ; ; LOOP TO THE END OF THE TABLE ; LP2END: LD A,(HL) ;CHECK FOR 0FFFFH AT END OF TABLE INC HL AND (HL) ;A=0FFH IF SO INC HL ;PT TO CURR CONTROL TYPE INC HL ;PT TO NEXT CONTROL ADDRESS INC A ;A=0 AND ZERO FLAG SET IF AT END JR NZ,LP2END ;CONTINUE UNTIL AT END OF TABLE LD D,H ;DE=HL=PTR TO NEW LAST TABLE ENTRY LOC LD E,L INC HL ;PT TO ENTRY AFTER LAST ENTRY IN TABLE INC HL INC HL ;HL PTS TO NEW LAST TABLE ENTRY LOCATION EX DE,HL ;DE PTS TO NEW, HL PTS TO OLD POP BC ;BC=ADDRESS OF ENTRY TO INSERT BEFORE ; ; EXPAND THE TABLE BY 3 PLACES UNTIL THE PROPER PLACE IS REACHED ; EXPTBL: DEC HL ;BACK UP DEC DE LD A,(HL) ;COPY PREVIOUS BYTE INTO NEW TABLE LOCATION LD (DE),A LD A,L ;ARE WE AT ENTRY TO INSERT BEFORE? CP C JR NZ,EXPTBL ;CONTINUE IF NOT LD A,H ;CHECK HIGH BYTES CP B JR NZ,EXPTBL POP DE ;DE=NEW ENTRY ADDRESS, HL=ADDRESS TO INSERT AT LD (HL),E ;PLACE NEW ENTRY ADDRESS INTO TABLE INC HL LD (HL),D INC HL LD A,(OPCTP) ;PLACE NEW ENTRY TYPE INTO TABLE LD (HL),A RET ; ; SEARCH CTL TBL FOR AN ENTRY FOR (DE) ; ON EXIT, HL PTS TO LOW-ORDER BYTE OF CONTROL TABLE ENTRY IF MATCHED ; OR LESS THAN ; MATCH: C=0 ; NO MATCH: C=1 ; SCHCTL: LD HL,CTLTBL ;PT TO TABLE ; ; IF NO MATCH THEN CARRY IS SET ; SMORE: LD A,(HL) ;GET LOW ADDRESS INC HL ;PT TO HIGH AND (HL) ;AND IN HIGH ADDRESS; IF ADDR=0FFFFH, THEN A=0FFH DEC HL ;PT TO LOW ADDRESS INC A ;IF A=0FFH BEFORE, NOW A=0 SCF ;SET CARRY FLAG FOR ERROR RETURN RET Z ;RETURN IF A=0 (WE ARE AT END OF TABLE) INC HL ;PT TO HIGH ADDRESS LD A,D ;GET ADDRESS TO COMPARE AGAINST CP (HL) ;DO COMPARE DEC HL ;PT TO LOW ADDRESS RET C ;RETURN IF ADDRESS IS LESS THAN TABLE ENTRY JR NZ,NXTRY ;CONTINUE IF NOT THE SAME LD A,E ;GET LOW ADDRESS CP (HL) ;COMPARE TO LOW ADDRESS RET Z ;CARRY IS OFF AND ZERO IS SET IF COMPLETE MATCH RET C ;CARRY IS ON AND ZERO IS NOT SET IF TARGET IS LESS ; ; ADVANCE TO THE NEXT TABLE ENTRY ; NXTRY: INC HL ;PT TO HIGH ADDRESS INC HL ;PT TO TYPE OF NEXT CONTROL ENTRY INC HL ;PT TO LOW ADDRESS OF NEXT ENTRY IN TABLE JR SMORE ;CONTINUE ; ; DUMP CONTROL TABLE FROM ADDRESS IN DE ; CDUMP: CALL SCHCTL ;FIND ENTRY IN CONTROL TABLE >= ADDRESS IN DE JR CDUMP2 ; ; DUMP ENTIRE CONTROL TABLE ; CDUMP1: LD HL,CTLTBL ;PT TO FIRST ENTRY IN CONTROL TABLE CDUMP2: CALL BRKCHK ;CHECK FOR ABORT LD E,(HL) ;GET ADDRESS OF CONTROL ENTRY IN DE INC HL LD D,(HL) INC HL LD A,D ;CHECK FOR END OF TABLE AND E ;END IF DE=0FFFFH INC A ;SET A TO 0 IF SO JR NZ,MOREDMP CALL CRLF ;DONE, SO OUTPUT NEW LINE AND PRINT CONTROL INFO CALL CTLST JP GETCMD ; ; DUMP CONTROL TABLE ENTRY TO USER ; MOREDMP: PUSH DE PUSH HL CALL SYMSCH ;SEARCH FOR A SYMBOL WHOSE VALUE = ADDRESS IN DE JR C,AHEAD ;SKIP IF NOT FOUND ; ; PRINT A SYMBOL SINCE IT WAS FOUND; SYMBOL PTED TO BY HL ; CALL IECNT ;INIT ECNT CALL CRLF ;NEW LINE PRNTSYM: LD A,(HL) ;OUTPUT CHARS OF SYMBOL CALL COUT ;... COUNT IN B FROM SYMSCH INC HL DJNZ PRNTSYM LD A,':' ;OUTPUT COLON AFTER SYMBOL CALL COUT ; ; OUTPUT CONTROL TABLE ENTRY ; AHEAD: POP HL ;GET PTR TO CONTROL MODE POP DE ;GET ADDRESS OF ENTRY CALL SPACE ;2 S CALL SPACE EX DE,HL ;ADDRESS IN HL CALL PVALUE ;PRINT VALUE OF ADDRESS LD A,'=' ;PRINT DELIMITERS CALL COUT LD A,' ' CALL COUT EX DE,HL ;RESTORE HL AS PTR TO CONTROL MODE LD A,(HL) ;GET CONTROL MODE LETTER CALL COUT ;PRINT IT CALL SPACE ; OUT CALL SPACE CALL SPCRLF ;OUTPUT NEW LINE OCCASIONALLY INC HL ;PT TO NEXT CONTROL TABLE ENTRY JR CDUMP2 ; ; SAVE THE CONTROL TABLE ON DISK ; SVCTL: CALL SVCTL0 ;USE ROUTINE JP GETCMD ; ; ROUTINE TO SAVE THE CONTROL TABLE ON DISK ; SVCTL0: CALL OPEN ;OPEN FILE LD HL,CTLTBL ;PT TO TABLE SVCTL1: LD E,(HL) ;GET ADDRESS IN DE INC HL LD D,(HL) INC HL LD A,D ;CHECK FOR END (0FFFFH) AND E INC A ;A=0 IF SO JR Z,CTLSVED CALL EXPND ;OUTPUT ADDRESS IN DE AS 4 HEX CHARS LD A,',' ;OUTPUT COMMA CALL WRTFILE LD A,(HL) ;OUTPUT CONTROL MODE CHAR CALL WRTFILE LD A,0DH ;OUTPUT NEW LINE CALL WRTFILE LD A,0AH CALL WRTFILE INC HL ;PT TO NEXT CONTROL TABLE ENTRY JR SVCTL1 ; ; THE CONTROL TABLE HAS BEEN SAVED ; CTLSVED: LD A,1AH ;WRITE EOF CALL WRTFILE CALL NXTRCRD RET ; ; READ IN A CONTROL TABLE ; ISCTL: CALL CTLRD ;READ CONTROL FILE JP STAT ;PRINT STATISTICS ; ; ROUTINE TO READ IN A CONTROL TABLE ; CTLRD: CALL RDOPEN ;OPEN FILE FOR READING LD HL,CTLTBL ;PT TO CONTROL TABLE LUP: CALL READMA ;READ NEXT CHAR LD DE,0 ;SET VALUE = 0 NUMLUP: CP 1AH ;ERROR IF EOF ENCOUNTERED JR Z,TERMF CP ',' ;DONE WITH NUMBER IF COMMA FOUND JR Z,STRDE CP '9'+1 ;CHECK FOR DIGIT JR C,NUM ;PROCESS IF SO SUB 7 ;ADJUST FOR 'A'-'F' NUM: SUB '0' ;CONVERT HEX ASCII TO BINARY EX DE,HL ;VALUE IN HL ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 ADD A,L ;ADD IN NEW VALUE LD L,A EX DE,HL ;VALUE BACK IN DE CALL READMA ;READ NEXT CHAR JR NUMLUP ;CONTINUE ; ; STORE THE ADDRESS ACCUMULATED IN DE INTO THE CONTROL TABLE ; STRDE: LD (HL),E ;STORE ADDRESS INC HL LD (HL),D INC HL CALL READMA ;READ CONTROL MODE CHAR LD (HL),A ;STORE IT INC HL ;PT TO NEXT CONTROL TABLE ENTRY JR LUP ; ; STORE ENDING 0FFFFH IN CONTROL TABLE ; TERMF: LD (HL),0FFH INC HL LD (HL),0FFH RET ; ;COMMAND: ; ; COMMENT ROUTINE. IT ADDS OR LISTS COMMENTS ; CMNT: CALL AREACK ;VERIFY THAT COMMENT TABLE EXISTS LD HL,INBUF+3 ;PT TO CHAR AFTER COMMAND LD A,(HL) ;GET IT CP 0DH ;DONE? JP Z,LSTCMT ;YES, SO LIST COMMENTS CP 'O' ;LOOK FOR 'ON/OFF' SWITCH JR NZ,CMNT1 INC HL LD A,(HL) ;SECOND CHARACTER OF THE COMMENT SBC A,'F' ;CREATE A 0 FOR 'OFF' JR Z,CMNT2 CP 'N'-'F' ;LOOK FOR AN 'N' (FOR 'ON') JP NZ,WHAT CMNT2: LD (XCSW),A ;TURN OFF COMMENTS JP GETCMD ; ; PROCESS NEW COMMENT ENTRY ; CMNT1: CALL CNVRT ;GET ADDRESS IN DE INC HL ;PT TO NEXT CHAR CP 0DH ;IF DONE, WE DELETE COMMENT JP Z,ONECMT CP ' ' ; OR ',' SAYS TEXT FOLLOWS JR Z,CMNT0 CP ',' JP NZ,WHAT ;ERROR IF NOT , , OR ',' CMNT0: PUSH HL ;SAVE PTR TO NEXT CHAR CALL CMCHK ;CHECK FOR COMMENT ALREADY AT ADDRESS IN DE JR C,ADDCMT ;IF NOT, JUST ADD COMMENT CALL DELCMT ;IF SO, FIRST DELETE EXISTING COMMENT ; ; ADD COMMENT TO COMMENT TABLE ; ADDCMT: POP HL ;GET PTR PUSH HL LD A,(HL) ;CHECK FOR ANY TEXT CP 0DH ;IF NONE, OLD COMMENT IS JUST DELETED JP Z,GETCMD LD HL,(COMEND) ;PT TO END OF COMMENT TABLE LD (HL),E ;SAVE NEW ADDRESS OF COMMENT INC HL LD (HL),D INC HL POP DE ;PT TO FIRST CHAR OF COMMENT LD B,0 ;INIT CHAR COUNT TO ZERO PUSH HL ;SAVE ADDRESS TO CHAR COUNT OF COMMENT ; ; SAVE TEXT OF COMMENT ; STRTXT: INC HL ;PT TO POSITION TO STORE AT LD A,(DE) ;GET COMMENT TEXT LD (HL),A ;STORE IT INC DE ;PT TO NEXT INC B ;INCR CHAR COUNT LD A,(DE) ;CHECK FOR DONE CP 0DH ;DONE IF JR NZ,STRTXT ;CONTINUE IF NOT INC HL ;PT TO ADDRESS AFTER LD (COMEND),HL ;SET PTR TO END OF COMMENT TABLE LD (HL),0FFH ;STORE 0FFFFH AS NEXT ENTRY INC HL LD (HL),0FFH POP HL ;GET PTR TO COMMENT CHAR COUNT LD (HL),B ;SAVE CHAR COUNT JP GETCMD ; ; CHECK FOR A COMMENT AT THE ADDRESS IN DE ; MATCH: CARRY IS OFF (NC CONDITION) ; CMCHK: LD HL,(COMST) ;PT TO START OF COMMENT TABLE CMCHK1: LD A,(HL) ;CHECK ADDRESS FOR 0FFFFH INC HL AND (HL) DEC HL INC A ;A=0 IF SO SCF ;PREP FOR ERROR RETURN RET Z ;NOT FOUND IF A=0 INC HL ;PT TO ADDRESS HIGH LD A,D ;GET TARGET ADDRESS IN DE CP (HL) ;COMPARE AGAINST THAT STORED DEC HL ;PT TO ADDRESS LOW JR NZ,NXTC ;IF NOT A MATCH, CONTINUE LD A,E ;COMPARE LOW BYTES CP (HL) RET Z ;THERE IS A COMMENT AT THIS ADDRESS, SO CARRY=1 NXTC: INC HL ;PT TO CHAR COUNT INC HL LD A,(HL) ;GET CHAR COUNT CALL SKIP ;SKIP TO NEXT COMMENT INC HL ;PT TO LOW BYTE OF NEXT COMMENT JP CMCHK1 ; ; DUMP COMMENT TABLE FROM A GIVEN ADDRESS FORWARD ; ONECMT: CALL CMCHK ;FIND COMMENT REFD IN DE JR LSTAGN ; ; DUMP ENTIRE COMMENT TABLE ; LSTCMT: LD HL,(COMST) ;PT TO FIRST COMMENT LSTAGN: CALL BRKCHK ;CHECK FOR ABORT LD E,(HL) ;GET ADDRESS OF COMMENT IN DE INC HL LD D,(HL) INC HL LD A,D ;CHECK FOR 0FFFFH AS END OF TABLE AND E INC A ;A=0 IF SO JP Z,GETCMD ;DONE IF SO EX DE,HL ;VALUE IN HL CALL PVALUE ;PRINT IT EX DE,HL ;VALUE IN DE, PTR TO COMMENT CHAR COUNT IN HL LD A,';' ;PRINT SEMICOLON BEFORE COMMENT CALL COUT LD B,(HL) ;GET CHAR COUNT IN B TEXT: INC HL ;PT TO COMMENT CHAR LD A,(HL) ;GET AND PRINT IT CALL COUT DJNZ TEXT ;CONTINUE UNTIL DONE CALL CRLF ;NEW LINE INC HL ;PT TO ADDRESS OF NEXT COMMENT JR LSTAGN ;CONTINUE ; ; DELETE AN EXISTING COMMENT WHOSE ADDRESS IS IN DE; HL PTS TO CMT TABLE ; DELCMT: LD A,(HL) ;CHECK FOR END OF COMMENT TABLE INC HL AND (HL) INC A ;A=0 IF AT END RET Z DEC HL ;PT TO ADDRESS IN CURRENT COMMENT PUSH DE ;SAVE ADDRESS TO DELETE LD D,H ;SAVE ADDRESS OF CURRENT COMMENT IN DE LD E,L INC HL ;PT TO CHAR COUNT OF CURRENT COMMENT INC HL LD A,(HL) ;GET IT IN A CALL SKIP ;SKIP TO NEXT COMMENT INC HL ;PT TO ITS ADDRESS LD B,0 ;INIT TO NOT DONE FOR LOOP ; ; COPY (HL) TO (DE) UNTIL FFFFH IS ENCOUNTERED ; SHFTCT: LD A,(HL) ;GET CHAR LD (DE),A ;PUT CHAR INC HL ;PT TO NEXT INC DE LD C,A ;DONE IF BC=0FFFFH AND B INC A ;A=0 IF DONE LD B,C JR NZ,SHFTCT ;CONTINUE UNTIL TWO SUCCESSIVE FF'S FOUND EX DE,HL ;SET END OF COMMENT TABLE DEC HL DEC HL LD (COMEND),HL POP DE RET ; ; CHECK TO SEE THAT AREA FOR COMMENTS WAS DEFINED (START <> 0) AND ; ABORT WITH ERROR MESSAGE IF NOT ; AREACK: LD HL,(COMST) ;HL=START ADDRESS LD A,H OR L RET NZ ;ERROR IF ZERO CALL PSTRNG DEFB '++ COMMAND IGNORED ++',0DH DEFB 0AH,'++ Issue ''UNNNN'' to tell ' DEFB 'DASM to use address ' DEFB 'NNNN',0DH,0AH,'as the start ' DEFB 'of the comments table ++',0DH DEFB 0AH,0 JP GETCMD ; ;COMMAND: U ; DEFINE THE COMMENTS AREA ; UAREA: LD HL,INBUF+3 ;CHECK ARGS LD A,(HL) CP 0DH ;ERROR IF JUST JP Z,WHAT CP '.' ;ERROR IF SYMBOL JP Z,WHAT CALL CNVRT ;CONVERT TO NUMBER IN DE EX DE,HL ;... IN HL LD A,H ;CHECK FOR WITHIN RANGE CP (SYMTAB+600H) SHR 8 ;THIS ALLOWS 600H BYTES FOR SYM TBL JR C,UAREA0 ;ERROR IF LESS LD (COMST),HL ;SET START AND END OF TABLE LD (COMEND),HL LD (HL),0FFH ;SET ENDING 0FFFFH IN TABLE INC HL LD (HL),0FFH JP GETCMD UAREA0: CALL PSTRNG ;PRINT ERROR MESSAGE DEFB 'NO!! Address is less than ' DEFB 0 LD HL,SYMTAB+600H LD L,0 CALL PVALUE CALL CRLF JP GETCMD ; ; HANDLE SYMBOLS FOR THE DISASSEMBLER; ADDRESS IN PC ; IF A SYMBOL EXISTS AT THIS ADDRESS, PRINT IT ; HSYM: PUSH DE PUSH HL LD A,1 ;ENABLE DISK OUTPUT LD (WRTENAB),A LD HL,(PC) ;GET ADDRESS OF PC EX DE,HL ;... IN DE CALL SYMSCH ;LOOK FOR SYMBOL JP C,RESUME ;GOTO RESUME IF NO SYMBOL LD C,B ;GET CHAR COUNT OF SYMBOL INTO C PUSH HL ;SAVE PTR TO IT ; ; CHECK TO SEE THAT SYMBOL CONTAINS NO + OR -; DON'T PRINT IF IT DOES ; HSYM0: LD A,(HL) ;GET CHAR CP '+' ;CHECK IT JR Z,HSYM1 CP '-' JR Z,HSYM1 INC HL ;PT TO NEXT DEC C ;CONTINUE TO END OF SYMBOL JR NZ,HSYM0 POP HL ;PT TO SYMBOL CALL PRNT ;PRINT THE SYMBOL LD A,':' ;.. AND A FOLLOWING COLON CALL COUT CALL TAB ;PRINT THE TAB CALL PDERTN ;PRINT THE ADDRESS AS A COMMENT (ADR IN DE) CALL CRLF ;NEW LINE JR RESUME ;CONTINUE HSYM1: POP HL RESUME: XOR A ;PRINT ADDRESS OF PC ON CRT LD (WRTENAB),A ;.. BUT NOT INTO THE FILE CALL SPACE ; OVER CALL SPACE LD HL,(PC) ;PRINT PC VALUE CALL PVALUE LD A,1 ;REENABLE WRITE OF MNEMONIC LD (WRTENAB),A CALL TAB ;TAB FOR FOLLOWING MNEMONIC POP HL POP DE RET ; ; BUILD A SYMBOL IN INBUF FOR THE VALUE IN DE ; BLDSYM: LD HL,INBUF ;PT TO INBUF LD (HL),'L' ;STORE LEADING L INC HL ;PT TO NEXT CHAR LD A,D ;GET VALUE IN DE CALL ACCTOASC ;STORE AS ASCII CHARS IN BUFFER LD A,E CALL ACCTOASC LD HL,INBUF ;PT TO SYMBOL LD B,5 ;SYMBOL IS 5 CHARS LONG ; ; INSERT A SYMBOL ALPHABETICALLY INTO TABLE ; INSERT: CALL PLCSYM ;FIND SYMBOL JR C,NEWSYM ;PROCESS AS NEW IF NOT FOUND LD (HL),E ;IF FOUND, SET NEW ADDRESS FOR IT INC HL LD (HL),D RET ; ; INSERT NEW SYMBOL INTO TABLE; LOCATION TO INSERT AT PTED TO BY HL ; NEWSYM: PUSH HL PUSH DE PUSH BC LD HL,(SYMEND) ;MOVE THE TABLE BY LENGTH+3 LD D,H ;DE PTS TO END OF SYMBOL TABLE LD E,L LD A,B ;LENGTH OF SYMBOL IN A ADD A,3 ;LENGTH OF SYMBOL + 3 ADD A,L ;PT TO NEW END OF TABLE LD L,A LD A,H ADC A,0 LD H,A LD (SYMEND),HL ;NEW END OF SYMBOL TABLE INC HL ;PT TO LENGTH OF SYMBOL AFTER LAST ONE INC HL LD (HL),0 ;SET THIS TO ZERO TO MARK END OF TABLE DEC HL DEC HL LD B,H ;ADDRESS OF LAST BYTE IN BC LD C,L LD HL,(SYMRKR) ;ADDRESS OF REV DEST TO MOVE TO IN HL ; ; EXPAND THE TABLE UNTIL SPACE IS MADE AT THE NEW SPOT ; LUP3: LD A,E ;AT DESTINATION? CP L JR NZ,AHD LD A,D CP H JR Z,STICKAD ;DONE IF SO AHD: DEC DE ;COPY BACKWARDS (DE) TO (BC) DEC BC LD A,(DE) LD (BC),A JR LUP3 ; ; ENTER THE ADDRESS AND LENGTH ; STICKAD: POP BC POP DE LD (HL),E ;STORE ADDRESS OF SYMBOL INC HL LD (HL),D INC HL LD (HL),B ;STORE LENGTH OF SYMBOL POP DE ; ; STORE THE SYMBOL STRING ; STICKSM: INC HL LD A,(DE) LD (HL),A INC DE DJNZ STICKSM RET ; ; FIND SPOT FOR NEW SYMBOL PTED TO BY HL, VALUE IN DE, B=LENGTH OF SYMBOL ; RETURN: C=0 FOR MTCH, HL=SYMBOL ; PLCSYM: PUSH DE ;SAVE VALUE PUSH HL ;SAVE ADDRESS OF SYMBOL LD HL,SYMTAB ;PT TO SYMBOL TABLE ANTHR: POP DE ;GET SYMBOL ADDRESS IN DE PUSH DE INC HL ;PT TO SYMBOL CHAR COUNT INC HL PUSH HL LD A,(HL) ;GET CHAR COUNT INC HL ;PT TO FIRST CHAR OR A ;CHECK FOR END OF SYMBOL TABLE JR Z,NONE ;GOTO NONE IF AT END OF TABLE CP B ;COMPARE SYMBOL LENGTHS JR C,LESS ;NO MATCH IF NOT SAME LENGTH JR NZ,NTLESS LD C,A ;SYMBOL LENGTH IN C CALL CHKSTG ;COMPARE (DE) TO (HL) JR Z,FOUND JR C,NONE ; ; TARGET SYMBOL GOES BEHIND CURRENT SYMBOL ; LATER: POP HL ;GET ADDRESS OF SYMBOL TABLE SYMBOL LD A,(HL) INC HL CALL SKIP ;SKIP TO NEXT JR ANTHR ; ; MATCH OF SYMBOLS ; FOUND: POP HL DEC HL DEC HL POP DE POP DE OR A ;RET WITH CARRY CLEAR FOR MATCH RET ; ; CHECK SHORTER STRING FOR PARTIAL MATCH ; LESS: LD C,A CALL CHKSTG JR NC,LATER JR NONE NTLESS: LD C,B CALL CHKSTG JR Z,NONE JR NC,LATER ; ; THERE IS NO SYMBOL FOR THIS VALUE, SO THIS VALUE SHOULD GO AT HL ; NONE: POP HL DEC HL DEC HL LD (SYMRKR),HL ;SET MARKER POP HL POP DE SCF ;SET CARRY FOR NO MATCH RET ; ; SEARCH THE SYMBOL TABLE FOR AN ENTRY WHOSE VALUE IS DE ; MATCH: C=0 ; SYMSCH: LD HL,SYMTAB ;PT TO SYMBOL TABLE ; ; (HL) IS START OF SYMBOL; (B) IS LENGTH ; MORE: LD A,(HL) ;GET AND COMPARE SYMBOL TABLE VALUES INC HL CP E JR NZ,SKPOVR LD A,(HL) CP D JR Z,FNDSYM ; ; GOTO NEXT SYMBOL ; SKPOVR: INC HL ;CHECK CHAR COUNT FOR DONE LD A,(HL) ;0 IF DONE OR A SCF ;SET CARRY FOR NO MATCH IF SO RET Z INC HL ;PT TO NEXT SYMBOL ADD A,L LD L,A JR NC,MORE INC H JR MORE ; ; RETURN WITH NO CARRY AND LENGTH IN B IF MATCHED ; FNDSYM: INC HL LD A,(HL) INC HL LD B,A OR A ;MATCH RET NZ SCF ;NO MATCH RET ; ;COMMAND: E ; PLACE A SYMBOL IN THE SYMBOL TABLE ; ENTER: LD HL,INBUF+3 ;CHECK FOR CHARS AFTER THE E CALL CNVRT ;GET VALUE LD A,(HL) ;CHECK FOR ERROR CP ' ' ;MUST BE FOLLOWED BY OR ',' JR Z,ENTER0 CP ',' JP NZ,WHAT ; ; GET SYMBOL ; ENTER0: INC HL ;PT TO SYMBOL LD A,(HL) ;GET '.' CP '.' ;MUST BE '.' JP NZ,WHAT PUSH DE ;SAVE THE SYMBOL'S VALUE PUSH HL ;SAVE THE BUFFER PTR CALL SYMSCH ;RETURN WITH C=0 FOR MATCH ;.. B=LENGTH HL=START OF STRING JR C,ENTER1 ;NOTHING TO DELETE PUSH HL CALL CRLF ;PRINT MESSAGE THAT SYMBOL WAS KILLED CALL PRNT CALL PSTRNG DEFB ' was Killed',0DH,0AH,0 POP HL DEC HL DEC HL DEC HL CALL KILL0 ;KILL SYMBOL ENTER1: POP HL PUSH HL CALL LNGTH ;COMPUTE LENGTH OF SYMBOL IN B POP DE LD A,B ;CHECK FOR SYMBOL TOO LONG CP SYMMAX+1 JR C,ENTER2 PUSH HL LD BC,SYMMAX ;SET TO MAX LENGTH LD H,D ;HL=DE LD L,E INC HL ;ADD 1 FOR 1ST CHAR ADD HL,BC LD (HL),0 ;TERMINATE SYMBOL LD B,C ;B=SYMMAX POP HL ENTER2: POP DE CALL INSERT ;INSERT SYMBOL INTO SYMBOL TABLE JP GETCMD ; ;COMMAND: K ; DELETE A SYMBOL FROM THE TABLE ; KILL: LD HL,INBUF+3 ;CHECK FOR SYMBOL SPECIFIED LD A,(HL) ;MUST BE '.' CP '.' JP NZ,WHAT CALL LNGTH ;GET LENGTH IN B CALL PLCSYM ;FIND SYMBOL PTED TO BY HL JP C,WHAT ;ERROR IF NOT FOUND CALL KILL0 ;KILL IT JP GETCMD ; ; KILL THE SYMBOL WHOSE VALUE IS PTED TO BY HL ; KILL0: LD B,H ;SAVE PTR IN BC LD C,L INC HL INC HL LD A,(HL) ;GET THE LENGTH OF THE SYMBOL INC HL CALL SKIP ;SKIP TO NEXT EX DE,HL ;DE PTS TO NEXT SYMBOL LD HL,(SYMEND) ;SHIFT THE SYMBOL TABLE DOWN TO DELETE SYM LUP4: LD A,E ;SHIFT COMPLETE? CP L JR NZ,AHD1 LD A,D CP H JR Z,DEAD AHD1: LD A,(DE) ;COPY DOWN LD (BC),A INC BC INC DE JR LUP4 ; ; THE SYMBOL IS DEAD -- SET NEW END OF SYMBOL TABLE ; DEAD: LD H,B LD L,C LD (SYMEND),HL ;SET END INC HL INC HL LD (HL),0 ;SET END OF TABLE MARKER RET ; ; SCAN SYMBOL STARTING AT (HL) AND RETURN WITH LENGTH IN B, PTR TO FIRST ; CHAR OF SYMBOL IN HL, AND PTR TO CHAR AFTER LAST CHAR IN SYMBOL IN DE ; LNGTH: INC HL ;PT TO FIRST CHAR LD B,0 ;INIT LENGTH PUSH HL CHAROK: LD A,(HL) ;GET CHAR INC HL ;PT TO NEXT INC B ;INCR LENGTH CP '+' ;CHECK FOR END OF SYMBOL MARK JR Z,CHAROK CP '-' JR Z,CHAROK CP '0' JR C,ILLSYM CP '9'+1 JR C,CHAROK CP 'A' JR C,ILLSYM CP 'Z'+1 JR C,CHAROK ; ; AN ILLEGAL CHARACTER FOUND IN A SYMBOL SCAN, SO SCAN IS DONE ; ILLSYM: DEC B ;COMPENSATE FOR COUNT JP Z,WHAT ;ERROR IF NO SYMBOL CHARS DEC HL ;BACK UP EX DE,HL ;PTR TO NEXT CHAR IN DE POP HL ;PT TO FIRST CHAR IN HL RET ; ; CONVERT THE ACCUMULATOR TO HEX ASCII IN MEMORY PTED TO BY HL (2 BYTES) ; ACCTOASC: PUSH AF CALL HINIB ;CONVERT HIGH NYBBLE LD (HL),A ;STORE IT INC HL ;PT TO NEXT POP AF CALL LONIB ;CONVERT LOW NYBBLE LD (HL),A ;STORE IT INC HL ;PT TO NEXT RET ; ; CONVERT THE HIGH NIBBLE OF A TO ASCII CHAR ; HINIB: RRA ;ROTATE HIGH NYBBLE TO LOW NYBBLE RRA RRA RRA ; ; CONVERT THE LOW NYBBLE OF A TO ASCII CHAR ; LONIB: AND 0FH ;MASK OUT NEW HIGH NYBBLE CP 10 ;CHECK FOR DIGIT JR C,AHD2 ;SKIP IF SO ADD A,7 ;ADD OFFSET OF 7 FOR '9' TO 'A' AHD2: ADD A,'0' ;CONVERT TO ASCII IN A RET ; ; PRINT THE HEX CHARACTERS FOR THE VALUE IN A ; PHEX: PUSH AF CALL HINIB ;PRINT HIGH NYBBLE CALL COUT POP AF CALL LONIB ;PRINT LOW NYBBLE JP COUT ; ; PRINT THE 4 HEX CHARACTERS FOR CONTENTS OF HL ; PVALUE: LD A,H ;PRINT HIGH BYTE CALL PHEX LD A,L ;PRINT LOW BYTE CALL PHEX ; ; PRINT A ; SPACE: LD A,' ' ;PRINT JP COUT ; ; READ HEX ASCII FROM COMMAND LINE AND CONVERT AND PLACE IN (DE) ; CNVRT: LD A,(HL) ;GET FIRST CHAR CP '.' ;IT IS A SYMBOL IF '.' JR Z,ITSASYM LD DE,0 ;INIT VALUE TO ZERO AGAIN: LD A,(HL) ;GET CHAR CP '0' ;IN RANGE? RET C ;DONE IF NOT CP '9'+1 ;RANGE? JR C,NUMER ;OK IF SO CP 'A' ;RANGE? RET C ;DONE IF NOT CP 'F'+1 ;RANGE? RET NC ;DONE IF NOT SUB 7 ;CONVERT FOR 'A'-'F' NUMER: SUB '0' ;CONVERT FROM ASCII TO BINARY EX DE,HL ;HL=VALUE ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 ADD A,L ;ADD IN NEW NYBBLE LD L,A EX DE,HL ;DE=VALUE INC HL ;PT TO NEXT CHAR JR AGAIN ;CONTINUE ; ; EVALUATE THE SYMBOL IN MEMORY AND RETURN WITH VALUE IN DE ; ITSASYM: CALL LNGTH ;DETERMINE LENGTH OF SYMBOL PUSH DE CALL PLCSYM ;FIND IT IN TABLE JP C,WHAT ;ERROR IF NOT FOUND LD E,(HL) ;PUT ITS VALUE IN DE INC HL LD D,(HL) POP HL LD A,(HL) RET ; ; OPEN A FILE FOR READING ; RDOPEN: PUSH HL LD HL,0100H ;SET DMA TO 100H LD (DMAPTR),HL XOR A ;SET NEXT RECORD FIELD TO 0 LD (FCBNR),A LD DE,FCB ;PT TO FCB LD C,0FH ;OPEN THE FILE CALL BDOS POP HL INC A ;FILE FOUND? RET NZ ;RET IF SO CALL PSTRNG ;ERROR IF NOT DEFB ' File Not Found',0DH,0AH,0 EX (SP),HL ;SAVE HL ON STACK POP HL ;RESTORE HL RET ; JP GETCMD ;OLD ERROR RETURN ; ; READ NEXT BYTE FROM DMA BUFFER AND RETURN IT IN A ; READMA: PUSH HL ;SAVE HL LD HL,(DMAPTR) ;PT TO NEXT BYTE LD A,H ;BEYOND END OF BUFFER? CP 1 ;1 IF SO JR NZ,NOTREAD ;IF NOT, THEN GET THE BYTE PUSH BC ;SAVE BC, DE PUSH DE LD DE,FCB ;PT TO FCB LD C,14H ;READ RECORD INTO DMA ADDRESS CALL BDOS OR A ;SET FLAG FOR ERROR POP DE ;RESTORE REGS POP BC LD HL,RECLEN ;PT TO FIRST BYTE OF BUFFER JR NZ,ERROR ;ERROR IF EOF ENCOUNTERED NOTREAD: LD A,(HL) ;GET NEXT CHAR IN A INC HL ;PT TO CHAR AFTER LD (DMAPTR),HL ;SET PTR FOR LATER USE POP HL ;RESTORE HL RET ERROR: CP 3 JR C,RDDMA0 CALL PSTRNG DEFB '++ Unexpected EOF ++',0DH,0AH DEFB 0 JP GETCMD ; ; AT EOF ... SET ^Z AS RESPONSE CHAR FROM READ ; RDDMA0: LD A,1AH LD (HL),A JR NOTREAD ; ; OPEN FILE PTED TO BY FCB FOR OUTPUT ; OPEN: PUSH HL LD DE,FCB ;ERASE IT FIRST LD C,13H CALL BDOS LD DE,FCB ;NOW CREATE IT LD C,16H CALL BDOS INC A ;ERROR IN CREATING IT? JP Z,WHAT ;SAY SO (NO ROOM IN DIR) XOR A ;SET RECORD FIELD TO ZERO LD (FCBNR),A LD HL,RECLEN ;SET DMA ADDRESS LD (DMAPTR),HL POP HL RET ; ; WRITE THE NEXT RECORD TO OPEN FILE ; NXTRCRD: LD DE,FCB ;WRITE IT LD C,15H CALL BDOS OR A ;ERROR? JR NZ,WRTERR LD DE,FCB ;CLOSE THE FILE LD C,10H CALL BDOS INC A ;ERROR IN CLOSING? RET NZ CALL PSTRNG ;SAY SO IF SO DEFB '++ Close Error ++',0DH,0AH,0 JP GETCMD ; ; AN ERROR OCCURRED DURING A WRITE RECORD ATTEMPT ; WRTERR: CALL PSTRNG DEFB '++ Write Error ++',0DH,0AH,0 ; ; WRITE INTO THE DMA BUFFER AND WRITE TO DISK WHEN IT FILLS ; CHAR TO WRITE PASSED IN A ; WRTFILE: PUSH HL LD HL,(DMAPTR) ;GET PTR LD (HL),A ;STORE NEXT CHAR INC L ;PT TO NEXT LD (DMAPTR),HL ;SET NEXT DMA POP HL RET NZ ;IF L REACHED ZERO, BUFFER WAS FULL; RET IF NZ PUSH BC ;WRITE RECORD TO DISK AND REINIT DMA PTR PUSH DE PUSH HL LD DE,FCB ;DO THE WRITE LD C,15H CALL BDOS OR A ;ERROR? JR NZ,WRTERR LD HL,RECLEN ;RESET DMA PTR LD (DMAPTR),HL POP HL POP DE POP BC RET ; ; PRINT COMMENT IF PTED TO BY XCPTR ; DCRLF: LD HL,(XCPTR) LD A,H OR L ;LOOK FOR A COMMENT ADDRESS JR Z,DCRLF3 CALL TAB ;TABULATE COMMENT LD B,(HL) ;GET CHAR COUNT XOR A ;CHECK FOR NO COMMENT OR B JR Z,DCRLF2 DCRLF1: INC HL ;OUTPUT COMMENT LD A,(HL) CALL COUT DJNZ DCRLF1 DCRLF2: LD HL,0 ;SET NO COMMENT NOW LD (XCPTR),HL DCRLF3: LD (RPLPTR),HL ;SET RPLPTR=0 ; ; OUTPUT ; CRLF: LD A,0DH CALL COUT LD A,0AH JP COUT ; ; PRINT THE PROMPT ; PRTSTAR: LD A,'*' ; ; PRINT THE CHARACTER IN A ON CON: AND/OR DISK ; THE FOLLOWING FLAGS TAKE EFFECT: ; HUSH (QUIET MODE) -- IF =0, CON: OUTPUT, ELSE NO CON: OUTPUT ; FOPEN (FILE OPEN) AND WRTENAB (WRITE ENABLE) -- IF BOTH <>0, DISK ; OUTPUT ; CNTENAB (COUNT ENABLE) -- IF <>0, ENABLE COUNT (LCTR) ; COUT: PUSH AF ;SAVE REGS PUSH BC PUSH DE PUSH HL LD E,A ;CHAR IN E PUSH DE ;PREP TO PRINT CHAR LD C,2 ;USE BDOS OUTPUT LD A,(HUSH) ;QUIET MODE? OR A ;0=YES CALL Z,BDOS ;PRINT THE CHAR IF NOT QUIET MODE POP DE LD A,(FOPEN) ;GET FILE OPEN FLAG LD HL,WRTENAB ;PT TO FILE WRITE ENABLED FLAG AND (HL) ;IF BOTH ENABLED, WRITE CHAR TO DISK ALSO LD A,E ;CHAR IN A, NOT ZERO FLAG = DISK OUTPUT CALL NZ,WRTFILE ;WRITE TO DISK IF OK LD A,E ;CHECK FOR CP 0AH JR NZ,COUT1 LD A,(CNTENAB) ;DECREMENT THE LINE COUNT IF A WAS SENT OR A ;CHECK IF COUNTING ENABLED JR Z,COUT1 LD HL,LCTR ;PT TO LINE COUNT DEC (HL) ;DECREMENT IT COUT1: POP HL ;RESTORE REGS AND EXIT POP DE POP BC POP AF RET ; ; PROMPT AND READ A COMMAND LINE FROM THE KEYBOARD ; PROMPT: CALL PRTSTAR ;PRINT PROMPT LD DE,INBUF ;PT TO INPUT LINE BUFFER LD A,80 ;SET BUFFER SIZE LD (DE),A LD C,10 ;READ INTO BUFFER FCT CALL BDOS LD HL,INBUF+1 ;PT TO CHAR COUNT READ LD E,(HL) ;GET IT IN DE LD D,0 ADD HL,DE ;PT TO AFTER LAST CHAR IN BUFFER INC HL LD (HL),0DH ;STORE ENDING LD HL,INBUF+1 ;PT TO CHAR COUNT OF BUFFER ; ; CONVERT TO UPPER CASE ; UPPR: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CP 0DH ;DONE? JP Z,CRLF CP 61H ;SMALL A? JR C,UPPR ;OK IF LESS CP 7BH ;SMALL Z + 1? JR NC,UPPR ;OK IF MORE AND 5FH ;CAPITALIZE LD (HL),A ;PUT CHAR JR UPPR ;CONTINUE ; ; PRINT THE STRING: ADDR AT TOP OF STACK, TERMINATED BY 0 ; PSTRNG: XOR A ;DISABLE QUIET MODE AND DISK OUTPUT LD (WRTENAB),A LD (HUSH),A PSTG: EX (SP),HL ;PT TO STRING IN HL AND SAVE OLD HL LUP5: LD A,(HL) ;OUTPUT CHARS CALL COUT INC HL ;PT TO NEXT LD A,(HL) ;GET NEXT CHAR OR A ;DONE? JR NZ,LUP5 INC HL ;PT TO AFTER STRING EX (SP),HL ;RESTORE HL AND SET NEW RET ADR RET ; ; INITIALIZE SPECIAL CONSTANTS SO CODE IS REENTRANT ; INIT0: LD A,IBUFLEN ;SIZE OF INPUT LINE BUFFER LD (INBUF),A LD A,INITDLEN-1 ;INITIAL SIZE OF MEMORY DUMP LD (DMPLEN),A LD A,INITLCNT ;INITIAL SIZE OF LIST DISPLAY LD (NLINES),A LD (LCTR),A LD HL,BLNGTH ;INITIAL CTL PTR LD (NXTCTL),HL LD HL,INITPC ;INITIAL VALUE OF PC LD (DMPSTRT),HL LD (DMPEND),HL LD (PC),HL LD HL,INITOFF ;INITIAL OFFSET LD (OFFSET),HL LD HL,INITELST ;INITIAL END OF LISTING VALUE LD (ENDLST),HL LD HL,COMTBL ;INITIAL POSITION OF COMMENTS LD (COMST),HL LD (COMEND),HL RET ; ; INITIALIZE SYMBOL TABLE, CONTROL TABLE, AND COMMENTS TABLE ; SET EOL ; INIT: XOR A ;A=0 LD (SYMTAB+2),A ;CLEAR SYMBOL TABLE BY SET CHAR COUNT OF LD HL,SYMTAB ;... FIRST ENTRY TO ZERO LD (SYMEND),HL ;SET END ADDRESS OF SYMBOL TABLE LD A,0DH ;SET END OF INPUT LINE LD (INBUF+3),A LD HL,0FFFFH ;SET NO ENTRIES IN CONTROL TABLE LD (CTLTBL),HL LD A,'I' ;SET FOR INSTRUCTION MODE INITIALLY LD (CTLTBL-1),A ;"PREVIOUS" CONTROL TABLE ENTRY IS SET TO 'I' LD HL,COMTBL ;SET ADDRESS OF COMMENT TABLE LD (COMST),HL ;START ADDRESS LD (COMEND),HL ;END ADDRESS LD (HL),0FFH ;CLEAR FIRST ENTRY TO NO COMMENT INC HL LD (HL),0FFH RET ; ; RETURN WITH ZERO IF STRINGS (DE) AND (HL) MATCH; LENGTH IS (C) ; CHKSTG: LD A,(DE) ;GET CHAR CP (HL) ;COMPARE RET NZ ;NO MATCH INC DE ;PT TO NEXT INC HL DEC C ;COUNT DOWN JR NZ,CHKSTG RET ; ; WATCH THE CONSOLE FOR A BREAK KEY AND ABORT IF SO ; BRKCHK: PUSH BC PUSH DE PUSH HL LD C,0BH ;CHECK FOR KEY PRESS CALL BDOS OR A ;NONE IF ZERO JR Z,AHD3 LD C,1 ;GET NEW CHAR CALL BDOS CP 3 ;CHECK FOR ^C JR Z,ABORT ;ABORT IF SO CALL CRLF ;ELSE NEW LINE JP GETCMD ABORT: CALL PSTRNG ;PROMPT USER DEFB 0DH,0AH,'Abort (Y/N)? ',0 CALL CHIN CP 'Y' JP Z,WBOOT JP GETCMD AHD3: POP HL POP DE POP BC RET ; ; CHECK FOR AN ASCII CHARACTER IN A ; RETURN WITH ZERO TRUE AND NO CARRY FOR , ; RETURN WITH NO CARRY IF PRINTABLE ASCII ; ISITASC: CP 0DH RET Z ;NO CARRY CP 0AH RET Z ;NO CARRY CP ' ' RET C ;CARRY IF < CP 7FH CCF ;CARRY IF > 7FH RET ; ; FILE TYPES ; TPALL: DEFB 'ALL' ;FILE TYPE FOR ALL (CTL, SYM, DOC, COM, AND ASM) FILES TPASM: DEFB 'ASM' ;ASM FILE TYPE TPCOM: DEFB 'COM' ;COM FILE TYPE TPCTL: DEFB 'CTL' ;CTL FILE TYPE TPSYM: DEFB 'SYM' ;SYM FILE TYPE TPDOC: DEFB 'DOC' ;DOC FILE TYPE DEFB '.' ; ; BUFFERS ; RELEND: DEFS 2 ;RELATIVE END ADDRESS OF COM FILE DMPSTRT: DEFS 2 ;STARTING ADDRESS OF DUMP (CURRENT ADDR ALSO) DMPEND: DEFS 2 ;ENDING ADDRESS OF DUMP DMPLEN: DEFS 2 ;NUMBER OF BYTES TO DUMP AT ONE TIME - 1 OFFSET: DEFS 2 ;OFFSET VALUE SYMEND: DEFS 2 ;END OF SYMBOL TABLE PC: DEFS 2 ;CURRENT VALUE OF PC ENDLST: DEFS 2 ;END OF LISTING PTR BIASED: DEFS 2 ;BIASED OFFSET COMST: DEFS 2 ;START ADDRESS OF COMMENTS COMEND: DEFS 2 ;END ADDRESS OF COMMENTS ADB: DEFS 1 ;FLAG FOR DB BUILD (0=HEX, <>0=ASCII AND HEX) FNDPC: DEFS 2 ;TEMP PC FOR FIND FUNCTION FNDADD: DEFS 2 ;TEMP ADDRESS FOR FIND FUNCTION ECNT: DEFS 1 ;TEMP LINE COUNTER NLINES: DEFS 1 ;NUMBER OF LINES FOR LIST LCTR: DEFS 1 ;COUNTER FOR LINES CNTENAB: DEFS 1 ;ENABLE LINE COUNT IF <> 0, ELSE DISABLE LINE CNT WRTENAB: DEFS 1 ;OUTPUT TO FILE IS ENABLED IF <> 0, NOT IF 0 RPLPTR: DEFS 2 ;MISC PTR XCPTR: DEFS 2 ;MISC PTR XCSW: DEFS 1 ;MISC PTR FOPEN: DEFS 1 ;FILE IS OPEN IF <> 0, NOT OPEN IF 0 HUSH: DEFS 1 ;DON'T PRINT COMMAND RESULT (QUIET MODE) IF 0 NXTCTL: DEFS 2 ;PTR TO NEXT CTL ENTRY BLNGTH: DEFS 1 ;BUFFER LENGTH SYMRKR: DEFS 2 ;SYMBOL MARKER DMAPTR: DEFS 2 ;PT TO DMA ADDRESS ASCBLD: DEFS 1 ;FLAG FOR A COMMAND (0=NOT A) BUILD: DEFS 1 ;FLAG FOR B COMMAND (0=NOT B) OPCTP: DEFS 3 ; ; INPUT LINE BUFFER ; INBUF: DEFS 1 ;SIZE OF BUFFER DEFS IBUFLEN+1 ;SIZE OF INPUT LINE AND BUFFER CONTENTS ; ; STACK AREA ; DEFS 40 ;STACK SPACE OLDST: DEFS 2 ;OLD STACK PTR ; DEFS 1 ;1 BYTE FOR INITIAL 'I' IN CONTROL TABLE ; ; NEXT PAGE AFTER PROGRAM MARKS BEGINNING OF BUFFER AREAS ; ORG $/100H*100H+100H ENDALL EQU $ END