; ******************************************* ; * MONITOR * ; * This program is based on the MONITOR * ; * program in 8080/Z80 Assembly Language * ; * Techniques for Improved Programing by * ; * Alan R. Miller. It has been expanded * ; * to include a set of new functions and * ; * an improved loader. This version is * ; * for North Star Horizon with a "window" * ; * at EC00. See the file MONITOR.DOC for * ; * more information. * ; * * ; * WRITTEN BY: Gary M. Morin * ; * ORIGINATED: November 14, 1982 * ; * MODIFIED: April 29, 1983 * ; * VERSION 2.3 * ; ******************************************* ; ORGIN EQU 100H ;PROGRAM START DEST EQU 0F800H ;PROGRAM DESTINATION HOME EQU DEST ;ABORT ADDRESS BOOT EQU 0H ;CP/M BOOT STACK EQU DEST-60H ; PTRTOG EQU DEST-1 ;PRINTER TOGGLE FLAG PORTN EQU STACK ;PORT AND BYTE IBUFP EQU STACK+3 ;BUFFER POINTER IBUFC EQU IBUFP+2 ;BUFFER COUNT IBUFF EQU IBUFP+3 ;INPUT BUFFER ; CTRC EQU 3 ;^C [BOOT CPM] CTRH EQU 8 ;^H TAB EQU 9 ;^I LF EQU 10 ;LF [LINE FEED] CR EQU 13 ;CR [CARRIAGE RETURN] CTRP EQU 16 ;^P [PRINTER TOGGLE] CTRQ EQU 17 ;^Q [RESTRT OUTPUT] CTRS EQU 19 ;^S [INTERUPT OUTPUT] CTRU EQU 21 ;^U [ERASE LINE] CTRX EQU 24 ;^X [ABORT] ESC EQU 27 ;ESCAPE DEL EQU 127 ;RUBOUT BACKSP EQU CTRH ;BACKSP CHAR APOS EQU (39-'0') AND 0FFH INC EQU 0DBH ;IN OP CODE OUTC EQU 0D3H ;OUT OP CODE RETC EQU 0C9H ;RET OP CODE ; ;================================================ ; North Star Equates ;================================================ ; CSTAT EQU 3 ;CONSOLE STATUS CDATA EQU 2 ;CONSOLE DATA CSTATO EQU 3 ;CONSOLE OUTPUT STATUS CDATAO EQU 2 ;CONSOLE OUTPUT DATA PSTATO EQU 5 ;PRINTER STATUS PDATAO EQU 4 ;PRINTER DATA INMSK EQU 2 ;INPUT MASK OMSK EQU 1 ;OUTPUT MASK ; ;================================================ ; Start of Code ;================================================ ; ORG ORGIN ; ;--> Save the old stack ; LXI H,0 ;zero HL DAD SP ;SP to HL SHLD OLDSTK ;save stack ; ;--> Locate important addresses ; LXI B,SOUEND-BEGIN+1 LXI H,PROEND LXI D,SOUEND-1 ; ;--> Move the code ; MVLP: LDAX D DCX H MOV M,A DCX D DCX B MOV A,B ;ZERO? ORA C ;LOW ORDER BYTE JNZ MVLP ; ;--> JUMP TO MONITOR NOW IN PLACE ; JMP START ; BEGIN: NOP ; ;********************************************** ; BEGINING OF THE ACTUAL PROGRAM ; ; CAUTION ; ANY LABELS ADDED AFTER THIS POINT MUST BE ; OF THE FORM $+OFFSET ;********************************************** ; OFFSET EQU DEST-BEGIN-1 ; START EQU $+OFFSET JMP COLD ;COLD START ; RESTRT EQU $+OFFSET JMP WARM ;WARM START ; ; ;--> CONSOLE STATUS ROUTINE ; INSTAT EQU $+OFFSET IN CSTAT ;GET STATUS BYTE ANI INMSK ;READY? RET ; ;--> CONSOLE INPUT ROUTINE ; INPUTT EQU $+OFFSET CALL INSTAT ;CHECK STATUS JZ INPUTT ;NOT READY INPUT2 EQU $+OFFSET IN CDATA ;GET BYTE ANI DEL CPI CTRX ;ABORT? JZ HOME ;YES CPI CTRC ;CANCEL? JZ BOOT ;YES CPI CTRP ;TOGGLE PRINTER? RNZ ;NO LDA PTRTOG ;CHECK FLAG CMA ;INVERT STA PTRTOG ;SAVE JMP INPUTT ;GET NEXT ; ; ;--> CONSOLE OUTPUT ROUTINE ; OUTT EQU $+OFFSET PUSH PSW OUT2 EQU $+OFFSET CALL INSTAT ;INPUT? JZ OUT4 ;NO CALL INPUT2 ;GET INPUT CPI CTRS ;FREEZE? JNZ OUT2 ;NO ; ;--> FREEZE OUTPUT UNTIL ^Q OR ^X ; OUT3 EQU $+OFFSET CALL INPUTT ;INPUT? ; OUT4 EQU $+OFFSET LDA PTRTOG ;PRINTER TOGGLE? ORA A JNZ OUT5 ;YES IN CSTATO ;CHECK STATUS ANI OMSK JZ OUT2 ;NOT READY POP PSW OUT CDATAO ;SEND DATA RET OUT5 EQU $+OFFSET IN PSTATO ;CHECK PTR STATUS ANI OMSK ;READY? JZ OUT2 ;NOT READY POP PSW OUT CDATAO ;SEND TO CONSOLE OUT PDATAO ;SEND TO PRINTER RET ; ;--> Cold start routine ; COLD EQU $+OFFSET LXI SP,STACK LXI D,STMSG ;MESSAGE CALL SENDM ;SENDIT MVI A,0 ;SET PTRTOG FLAG STA PTRTOG ;STORE IT ; ;--> Warm start routine ; WARM EQU $+OFFSET LXI H,WARM ;PUSH WARM ADDR PUSH H ; ON STACK CALL CRLF ;NEW LINE CALL INPLN ;CONSOLE LINE CALL GETCH ;GET CHARACTER ; ;--> MAIN COMMAND PROCESSOR ; AFTER ALAN R. MILLER ; SUI 'A' ;CONVERT OFFSET JC ERROR ; < A CPI 'Z'-'A'+1 JNC ERROR ; > Z ADD A ;DOUBLE LXI H,TABLE ;START MVI D,0 MOV E,A ;OFFSET DAD D ;ADD TO TABLE MOV E,M ;LOW BYTE INX H MOV D,M ;HIGH BYTE XCHG ;INTO H,L PCHL ;GO THERE ; ;--> COMMAND TABLE ; TABLE EQU $+OFFSET DW ASCII ;A, ASCII DW RETCPM ;B, BACK TO CPM DW CALLS ;C, CALL SUBROUTINE DW DUMP ;D, DUMP DW ERROR2 ;E DW FILL ;F, FILL DW GO ;G, GO DW HMATH ;H, HEX MATH DW IPORT ;I, PORT INPUT DW ERROR2 ;J DW ERROR2 ;K DW LOAD ;L, LOAD DW MOVE ;M, MOVE DW ERROR2 ;N DW OPORT ;O, PORT OUTPUT DW TOGLP ;P, TOGGLE PRINTER DW ERROR2 ;Q DW REPL ;R, REPLACE DW SEARCH ;S, SEARCH DW HELP ;T, COMMAND TABLE DW ERROR2 ;U DW VERM ;V, VERIFY MEMORY DW ERROR2 ;W DW REGS ;X, STACK POINTER DW ERROR2 ;Y DW ERROR2 ;Z ; ;--> INPUT A COMMAD LINE PLACE IT IN THE BUFFER ; INPLN EQU $+OFFSET MVI A,'-' ;PROMPT CALL OUTT MVI A,'>' ;PROMPT CALL OUTT ; INPL2 EQU $+OFFSET LXI H,IBUFF ;BUFFER ADDRESS SHLD IBUFP ;SAVE POINTER MVI C,0 ;COUNT ; INPLI EQU $+OFFSET CALL INPUTT ;CONSOLE CHAR CPI ' ' ;CONTROL? JC INPLC ;YES CPI DEL ;DELETE JZ INPLB ;YES CPI 'Z'+1 ;UPPER CASE? JC INPL3 ;YES ANI 5FH ;MAKE UPPER CASE ; INPL3 EQU $+OFFSET MOV M,A ;INTO BUFFER MVI A,32 ;BUFFER SIZE CMP C ;FULL? JZ INPLI ;YES, LOOP MOV A,M ;GET CHAR INX H ;INCREMENT POINTER INR C ;AND COUNT ; INPLE EQU $+OFFSET CALL OUTT ;SHOW CHAR JMP INPLI ;NEXT CHAR ; ;--> PROCESS CONTROL CHARACTER ; INPLC EQU $+OFFSET CPI CTRH ;^H? JZ INPLB ;YES CPI CR ;RETURN JNZ INPLI ;NO, IGNORE ; ;--> END OF INPUT LINE ; MOV A,C ;COUNT STA IBUFC ;SAVE ; ;--> CARRIAGE-RETURN, LINE FEED ROUTIN ; CRLF EQU $+OFFSET MVI A,CR CALL OUTT ;SEND CR MVI A,LF JMP OUTT ;SEND LF ; ;--> DELETE PRIOR CHARACTER IF ANY ; INPLB EQU $+OFFSET MOV A,C ;CHARACTER COUNT ORA A ;ZERO? JZ INPLI ;YES DCX H ;BACK POINTER DCR C ;AND COUNT MVI A,BACKSP ;CHARACTER JMP INPLE ;SEND ; ;--> GET A CHARACTER FROM CONSOLE BUFFER ; SET CARRY IF EMPTY ; GETCH EQU $+OFFSET PUSH H ;SAVE REGS LHLD IBUFP ;GET POINTER LDA IBUFC ;AND COUNT SUI 1 ;DECREMENT W/CARRY JC GETC4 ;NO MORE CHARACTERS STA IBUFC ;SAVE NEW COUNT MOV A,M ;GET CHARACTER INX H ;INCREMENT POINTER SHLD IBUFP ;AND SAVE ; GETC4 EQU $+OFFSET POP H ;RESTORE REGS RET ; ;--> SEND ASCII MESSAGE UNTIL BINARY ZERO ; IS FOUND. POINTER IS D,E ; SENDM EQU $+OFFSET LDAX D ;GET BYTE ORA A ;ZERO? RZ ;YES, DONE CALL OUTT ;SEND IT INX D ;POINTER JMP SENDM ;NEXT ; ;--> DUMP MEMORY IN HEXADECIMAL AND ASCII ; DUMP EQU $+OFFSET CALL RDHLDE ;RANGE ; DUMP2 EQU $+OFFSET CALL CRHL ;NEW LINE ; DUMP3 EQU $+OFFSET MOV C,M ;GET BYTE CALL OUTHX ;PRINT INX H ;POINTER MOV A,L ;MOVE LOW ORDER BYTE ANI 0FH ;LINE END JZ DUMP4 ;YES, ASCII ANI 3 ;SPACE CZ OUTSP ;4 BYTES JMP DUMP3 ;NEXT HEX ; DUMP4 EQU $+OFFSET CALL OUTSP PUSH D LXI D,-10H ;RESET LINE DAD D POP D ; DUMP5 EQU $+OFFSET CALL PASCI ;ASCII DUMP CALL TSTOP ;DONE MOV A,L ;NO ANI 0FH ;LINE END JNZ DUMP5 ;NO JMP DUMP2 ; ;--> DISPLAY MEMORY BYTE IN ASCII IF ; POSSIBLE, OTHERWISE GIVE DECIMAL PNT ; ; PASCI EQU $+OFFSET MOV A,M ;GET BYTE CPI DEL ;HIT BIT ON? JNC PASC2 ;YES CPI ' ' ;CONTROL CHARACTER? JNC PASC3 ;NO ; PASC2 EQU $+OFFSET MVI A,'.' ;CHANGE TO DOT ; PASC3 EQU $+OFFSET JMP OUTT ;SEND ; ;--> GET H,L AND D,E FROM CONSOLE ; CHECK THAT D,E IS LARGER ; RDHLDE EQU $+OFFSET CALL HHLDE ; RDHLD2 EQU $+OFFSET MOV A,E SUB L ;E - L MOV A,D SBB H ;D - H JC ERROR1 ;H,L BIGGER RET ; ;--> INPUT H,L AND D,E. SEE THAT 2 ; ADDRESSES ARE ENTERED ; HHLDE EQU $+OFFSET CALL READHL ;H,L JC ERROR1 ;ONLY 1 ADDR XCHG ;SAVE IN D,E CALL READHL ;D,E XCHG ;PUT BACK RET ; ;--> INPUT H,L FROM CONSOLE ; READHL EQU $+OFFSET PUSH D PUSH B ;SAVE REGS LXI H,0 ;CLEAR ; RDHL2 EQU $+OFFSET CALL GETCH ;GET CHARACTER JC RDHL5 ;LINE END CALL NIB ;TO BINARY JC RDHL4 ;NOT HEX DAD H ;TIMES 2 DAD H ;TIMES 4 DAD H ;TIMES 8 DAD H ;TIMES 16 ORA L ;ADD NEW CHARACTER MOV L,A JMP RDHL2 ;NEXT ; ;--> CHECK FOR BLANK AT END ; RDHL4 EQU $+OFFSET CPI APOS ;APOSTROPHE JZ RDHL5 ;ASCII INPUT CPI (' '-'0') AND 0FFH JNZ ERROR ;NO ; RDHL5 EQU $+OFFSET POP B POP D ;RESTORE RET ; ;--> CONVERT ASCII CHARACTERS TO BINARY ; NIB EQU $+OFFSET SUI '0' ;ASCII BIAS RC ; < 0 CPI 'F'-'0'+1 CMC ;INVERT RC ;ERROR, > F CPI 10 CMC ;INVERT RNC ;NUMBER 0-9 SUI 'A'-'9'-1 CPI 10 ;SKIP : TO RET ;LETTER A-F ; ; ;--> START NEW LINE, GIVE ADDRESS ; CRHL EQU $+OFFSET CALL CRLF ;NEW LINE ; ; PRINT H,L IN HEX ; OUTHL EQU $+OFFSET MOV C,H CALL OUTHX ;H ; OUTLL EQU $+OFFSET MOV C,L ; ; OUTPUT HEX BYTE FROM C AND A SPACE ; OUTHEX EQU $+OFFSET CALL OUTHX ; ; OUTPUT A SPACE ; OUTSP EQU $+OFFSET MVI A,' ' JMP OUTT ; ;--> OUTPUT A HEX BYTE FROM C ; BINARY TO ASCII HEX CONVERSION ; OUTHX EQU $+OFFSET MOV A,C RAR ;ROTATE RAR ;FOUR RAR ;BITS TO RAR ;RIGHT CALL HEX1 ;UPPER CHARACTER MOV A,C ;LOWER CHARACTER ; HEX1 EQU $+OFFSET ANI 0FH ;TAKE 4 BITS ADI 90H DAA ;DAA TRICK ACI 40H DAA JMP OUTT ; ;--> CHECK FOR END, H,L MINUS D,E ; INCREMENT H,L ; TSTOP EQU $+OFFSET INX H MOV A,E SUB L ; E - L MOV A,D SBB H ; D - H RNC ;NOT DONE POP H ;RAISE STACK RET ; ;--> ERROR ROUTINES ; ERROR EQU $+OFFSET MVI A,'?' CALL OUTT ;OUTPUT IT JMP RESTRT ;TRY AGAIN ; ERROR1 EQU $+OFFSET LXI D,E1MSG ;ERROR MESSAGE ADDR CALL SENDM JMP RESTRT ; ERROR2 EQU $+OFFSET LXI D,E2MSG ;ERROR MSG ADDR CALL SENDM JMP RESTRT ; ;--> BACK TO CPM GENTLY ; RETCPM EQU $+OFFSET LHLD OLDSTK SPHL RET ; ;--> HELP ROUTINE ; HELP EQU $+OFFSET LXI D,INSTR ;INSTRUCTIONS ADDRESS CALL SENDM JMP RESTRT ; ;--> TOGGLE PRINTER ON ; TOGLP EQU $+OFFSET LDA PTRTOG CMA STA PTRTOG JMP RESTRT ; ;--> ROUTINES TO CALL A SUBROUTINE AND TO ; 'GO' TO ANYPLACE IN THE MEMORY ; GO EQU $+OFFSET POP H ;RAISE STACK ; CALLS EQU $+OFFSET CALL READHL ;GET ADDRESS PCHL ;GO THERE ; ;--> LOAD HEX OR ASCII CHARACTER INTO MEMORY ; APOSTROPHE PERCEEDS ASCII CHAR ; CARRIAGE RETRUN PASSES OVER LOCATION ; LOAD EQU $+OFFSET CALL READHL ;ADDRESS ; LOAD2 EQU $+OFFSET CALL OUTHL ;PRINT IT CALL PASCI ;ASCII CALL OUTSP MOV C,M ;ORIG BYTE CALL OUTHEX ;HEX PUSH H ;SAVE PNTR CALL INPL2 ;INPUT CALL READHL ; BYTE MOV B,L ; TO B POP H CPI APOS JZ LOAD6 ;ASCII INPUT MOV A,C ;HOW MANY ORA A ;NONE? JZ LOAD3 ;YES ; LOAD4 EQU $+OFFSET CALL CHEKM ;INTO MEMORY ; LOAD3 EQU $+OFFSET INX H ;POINTER JMP LOAD2 ; ;--> LOAD ASCII CHARACTER ; LOAD6 EQU $+OFFSET CALL GETCH MOV B,A JMP LOAD4 ; ;--> COPY BYTE FROM B TO MEMORY ; AND SEE THAT IT GOT THERE ; CHEKM EQU $+OFFSET MOV M,B ;PUT IN MEM MOV A,M ;GET BACK CMP B ;SAME? RZ ;YES ; ERRP EQU $+OFFSET POP PSW ;RAISE STACK ; ERRB EQU $+OFFSET MVI A,'B' ;BAD ; ERR2 EQU $+OFFSET CALL OUTT CALL OUTSP JMP OUTHL ;POINTER ; ;--> DISPLAY STACK POINTER REGISTER ; REGS EQU $+OFFSET LXI H,0 DAD SP JMP OUTHL ; ;--> FILL A PORTION OF MEMORY ; FILL EQU $+OFFSET CALL HLDEBC ;RANGE BYTE CPI APOS ;APOSTROPHE JZ FILL4 ;YES, ASCII MOV B,C ; FILL2 EQU $+OFFSET MOV A,H ;FILL BYTE CPI STACK SHR 8 ;TO FAR JNC ERROR ;YES ; FILL3 EQU $+OFFSET CALL CHEKM ;PUT, CHECK CALL TSTOP ;DONE? JMP FILL2 ;NEXT ; FILL4 EQU $+OFFSET CALL GETCH ;ASCII CHAR MOV B,A JMP FILL3 ; ;--> GET H,L D,E AND B,C ; HLDEBC EQU $+OFFSET CALL HLDECK ;RANGE JC ERROR ;NO BYTE PUSH H CALL READHL ;3RD INPUT MOV B,H ;MOVE TO MOV C,L ; B,C POP H RET ; ;--> GET 2 ADDRESSES, CHECK THAT ; ADDITIONAL DATA IS INCLUDED ; HLDECK EQU $+OFFSET CALL HHLDE ;2ND ADDR JC ERROR1 ;THATS ALL JMP RDHLD2 ;CHECK ; ; ;--> MOVE A BLOCK OF MEMORY H,L-D,E TO B,C ; MOVE EQU $+OFFSET CALL HLDEBC ;3 ADDR ; MOVDN EQU $+OFFSET CALL MOVIN ;MOVE CHECK CALL TSTOP ;DONE? INX B ;NO JMP MOVDN ; MOVIN EQU $+OFFSET MOV A,M ;BYTE STAX B ;NEW LOCATION LDAX B ;CHECK CMP M ;IS IT THERE RZ ;YES MOV H,B ;ERROR MOV L,C ;INTO H,L JMP ERRP ;SHOW BAD ; ;--> SEARCH FOR 1 OR 2 BYTES OVER THE ; RANGE H,L D,E. BYTES ARE IN B,C ; B HAS CARRIAGE RETURN IF ONLY ONE ; BYTE. PUT SPACE BETWEEN BYTES IF TWO ; FORMAT: [START] [STOP] [BYTE1] [BYTE2] ; SEARCH EQU $+OFFSET CALL HLDEBC ;RANGE, 1ST BYTE ; SEAR2 EQU $+OFFSET MVI B,CR ;SET FOR 1 BYTE JC SEAR3 ;ONLY ONE PUSH H CALL READHL ;2ND BYTE MOV B,L ;INTO C POP H ; SEAR3 EQU $+OFFSET MOV A,M ;GET BYTE CMP C ;MATCH JNZ SEAR4 ;NO INX H ;YES MOV A,B ;ONLY ONE CPI CR JZ SEAR5 ;YES ; ;--> FOUND FIRST MATCH, CHECK FOR SECOND ; MOV A,M ;NEXT BYTE CMP B ;MATCH JNZ SEAR4 ;NO ; SEAR5 EQU $+OFFSET DCX H ;A MATCH PUSH B CALL CRHL ;SHOW ADDRESS POP B ; SEAR4 EQU $+OFFSET CALL TSTOP ;DONE? JMP SEAR3 ;NO ; ;--> ASCII SUB-COMMAND PROCESSOR ; ASCII EQU $+OFFSET CALL GETCH ;NEXT CHAR CPI 'D' ;DISPLAY JZ ADUMP CPI 'S' ;SEARCH JZ ASCS CPI 'L' ;LOAD JNZ ERROR ; ;--> LOAD ASCII CHARACTERS INTO MEMORY ; QUIT ON CONTROL-X ; CALL READHL ;ADDRESS CALL OUTHL ;PRINT IT ; ALOD2 EQU $+OFFSET CALL INPUTT ;NEXT CHARACTER CALL OUTT ;PRINT IT MOV B,A ;SAVE CALL CHEKM ;INTO MEMORY INX H ;POINTER MOV A,L ANI 7FH ;LINE END? JNZ ALOD2 ;NO CALL CRHL ;NEW LINE JMP ALOD2 ; ;--> DISPLAY MEMORY IN ASCII. ; ADUMP EQU $+OFFSET CALL RDHLDE ;RANGE ; ADMP2 EQU $+OFFSET MOV A,M ;GET BYTE CPI DEL ;HIGH BIT ON? JNC ADMP4 ;YES CPI ' ' ;CONTROL? JNC ADMP3 ;NO CPI CR ;CARRIAGE RETURN JZ ADMP3 ;YES, OK CPI LF ;LINE FEED JZ ADMP3 ;YES, OK CPI TAB JNZ ADMP4 ;SKIP OTHER MVI A,' ' ;SPACE FOR TAB ; ADMP3 EQU $+OFFSET CALL OUTT ;SEND ; ADMP4 EQU $+OFFSET CALL TSTOP ;DONE? JMP ADMP2 ;NO ; ;--> SEARCH FOR 1 OR 2 ASCII CHARACTERS ; NO SPACE BETWEEN ASCII CHARACTERS ; FORMAT [START] [STOP] 1 OR 2 ASCII CHARACTERS ; ASCS EQU $+OFFSET CALL RDHLDE ;RANGE CALL GETCH ;FIRST CHAR MOV C,A CALL GETCH ;2ND OR CR JC SEAR2 ;ONLY ONE CHARACTER MOV B,A ;2ND JMP SEAR3 ; ;--> INPUT FROM PORT ; IPORT EQU $+OFFSET CALL READHL ;PORT MOV C,L ;PORT TO C MVI A,INC ;IN CODE CALL PUTIO ;SETUP INPUT MOV L,A CALL OUTLL ;HEX VALUE ; ;--> PRINT L REGISTER IN BINARY (8080 VERSION) ; BITS EQU $+OFFSET MVI B,8 ;8 BITS ; BIT2 EQU $+OFFSET MOV A,L ADD A ;SHIFT LEFT MOV L,A MVI A,'0'/2 ;HALF OF 0 ADC A ;DOUBLE+CARRY CALL OUTT ;PRINT BIT DCR B JNZ BIT2 ;8 TIMES RET ; ;--> OUTPUT BYTE FROM DESIGNATED PORT ; FORMAT: O,[PORT],[BYTE] ; OPORT EQU $+OFFSET CALL READHL ;PORT MOV C,L CALL READHL ;DATA MVI A,OUTC ;OUT OPCODE ; ;--> I/O ROUTINE AFTER ALAN R. MILLER IN ; 8080/Z80 ASSEMBLY LANGUAGE TECHNIQUES ; FOR IMPROVED PROGRAMING ; PUTIO EQU $+OFFSET STA PORTN ;IN OR OUT CODE MOV A,C ;PORT NUMBER STA PORTN+1 MVI A,RETC ;RET OPCODE STA PORTN+2 MOV A,L ;OUTPUT BYTE JMP PORTN ;EXECUTE ; ;--> HEXADECIMAL MATH, ; HMATH EQU $+OFFSET CALL HHLDE ;TWO NUMBERS PUSH H ;SAVE HL DAD D CALL OUTHL ;PRINT IT POP H MOV A,L SUB E ;LOW BYTES MOV L,A MOV A,H SBB D MOV H,A ;HIGH BYTES JMP OUTHL ; ;--> REPLACE ONE HEX BYTE WITH ANOTHER ; OVER A GIVEN RANGE ; FORMAT: R[START] [STOP] [ORIG] [NEW] ; REPL EQU $+OFFSET CALL HLDEBC ;RANGE, 1ST BYTE JC ERROR ;NO 2ND PUSH H CALL READHL ;2ND BYTE MOV C,L ;INTO C POP H ; REPL2 EQU $+OFFSET MOV A,M ;FETCH BYTE CMP B ;A MATCH? JNZ REPL3 ;NO MOV M,C ;SUBSTITUTE MOV A,C CMP M ;SAME? JNZ ERRB ;NO, BAD ; REPL3 EQU $+OFFSET CALL TSTOP ;DONE? JMP REPL2 ; ;--> COMPARE TWO BLOCKS OF MEMORY ; FORMAT: V[1ST BEG.] [1ST END] [2ND BEG] ; VERM EQU $+OFFSET CALL HLDEBC ;THREE ADDRESSES ; VERM2 EQU $+OFFSET LDAX B ;FETCH BYTE CMP M ;SAME AS OTHER JZ VERM3 ;YES PUSH H ;DIFFERENT PUSH B CALL CRHL ;PRINT 1ST POINTER MOV C,M ;FIRST BYTE CALL OUTHEX ;PRINT IT MVI A,':' CALL OUTT POP H CALL OUTHL ;SECOND POINTER MOV C,M ;2ND BYTE CALL OUTHX ;PRINT IT MOV C,L ;RESTORE C MOV B,H ;AND B POP H ;AND H,L ; VERM3 EQU $+OFFSET CALL TSTOP ;DONE? INX B ;SECOND POINTER JMP VERM2 ; ;================================================ ; Messages ;================================================ ; STMSG EQU $+OFFSET DB CR,LF DB 'NORTH * STAR Monitor Version 2.4',CR,LF DB CR,LF DB 0 ; INSTR EQU $+OFFSET DB CR,LF DB 'ASCII LOAD, DUMP -->A[ L D S ] [1ST ADR] [2ND ADR] ',CR,LF DB ' or SEARCH',CR,LF DB 'BACK GENTLY -->B',CR,LF DB 'CALL SUBROUTINE -->C[ADR]',CR,LF DB 'DUMP MEMORY -->D[1ST ADR] [2ND ADR]',CR,LF DB 'FILL MEMORY -->F[1ST ADR] [2ND ADR] [HEX BYTE]',CR,LF DB ' -->F[1ST ADR] [2ND ADR] ''[ASCII]',CR,LF DB 'GO ANYWHERE -->G[ADR]',CR,LF DB 'HEX MATH + - -->H[1ST HEX] [2ND HEX]',CR,LF DB 'INPUT FROM PORT -->I[PORT NUMBER]',CR,LF DB 'LOAD MEMORY -->L[START ADR]',CR,LF DB ' ADR BYTE [NEW BYTE] ^X HALT',CR,LF DB 'MOVE MEMORY -->M[1ST ADR] [2ND ADR] [NEW START]',CR,LF DB 'OUTPUT TO PORT -->O[PORT NUMBER] [BYTE]',CR,LF DB 'PRINTER TOGGLE -->P',CR,LF DB 'REPLACE MEMORY -->R[1ST ADR] [2ND ADR] [TARGET] [BYTE]' DB CR,LF DB 'SEARCH FOR BYTE -->S[1ST ADR] [2ND ADR] [BYTE1] [BYTE2]' DB CR,LF DB 'COMMAND TABLE -->T',CR,LF DB 'COMPARE BLOCKS -->V[1ST ADR] [2ND ADR] [1ST ADR BLOCK2]' DB CR,LF DB 'DISP STACK POINT -->X',CR,LF DB CR,LF DB 0 ; E1MSG EQU $+OFFSET DB 'ADDRESS RANGE ERROR',CR,LF DB 0 ; E2MSG EQU $+OFFSET DB 'COMMAND ERROR',CR,LF DB 0 ; ;================================================ ; End of Program ;================================================ ; PROEND EQU $+OFFSET SOUEND: NOP ; OLDSTK EQU $+OFFSET DS 2 ; END