Add MON85 for MiniMax 8085
authorSergey Kiselev <skiselev@gmail.com>
Wed, 22 Sep 2021 19:19:00 +0000 (12:19 -0700)
committerSergey Kiselev <skiselev@gmail.com>
Wed, 22 Sep 2021 19:19:00 +0000 (12:19 -0700)
Signed-off-by: Sergey Kiselev <skiselev@gmail.com>
software/mon85/mon85-mini85.asm [new file with mode: 0644]

diff --git a/software/mon85/mon85-mini85.asm b/software/mon85/mon85-mini85.asm
new file mode 100644 (file)
index 0000000..0ce036b
--- /dev/null
@@ -0,0 +1,1764 @@
+;\r
+; MON85: A software debugger for the 8080/8085 processor\r
+;\r
+; Copyright 1979-2007 Dave Dunfield\r
+; All rights reserved.\r
+;\r
+; Version 1.2 - 2012 Roman Borik\r
+;\r
+; New in version 1.2\r
+; - Support for undocumented 8085 instructions.\r
+;   DSUB B, ARHL, RDEL, LDHI d8, LDSI d8, LHLX D, SHLX D, JNK a16, JK a16, RSTV\r
+; - Command R displays all flags of F register (SZKA3PVC). If flag is not set\r
+;   dash '-' is displayed.\r
+; - Added restart vector RST 8 (0040h) for possibility to handle RSTV call.\r
+; - Changed TRACE mode. After entering TRACE mode, instruction on actual PC and\r
+;   content of registers (if it is switched on) are displayed.\r
+;   Entering a space ' ' executes this instruction, and returns to the 'T>'\r
+;   prompt with the next instruction.\r
+; - Instructions LXI, DAD, INX, DCX displays argument 'SP' rather than 'S'.\r
+; - Commands that requires 1 byte parameter raises error if entered value\r
+;   not fit to 1 byte.\r
+; - Command 'C' checks overlap of source and destination block and for copying\r
+;   uses appropriate direction.\r
+; - Command 'F' checks <start> and <end> parameters and raises error,\r
+;   if <end> is lower than <start>.\r
+; - Added command 'H' to send out memory content in Intel HEX format.\r
+; - Sending of LF and CR characters were reversed and are sent in the usual\r
+;   order - CR first and followed by LF.\r
+\r
+\r
+ROM    EQU     0000h           ; Debugger goes here\r
+DRAM   EQU     0FFA0h          ; Debugger RAM (96 bytes required)\r
+\r
+;\r
+; Debugger data area (in RAM)\r
+;\r
+       ORG     DRAM            ; Monitor data goes here\r
+;\r
+UBASE: DS      2               ; Base address of user program\r
+HL:    DS      2               ; Saved HL register pair\r
+DE:    DS      2               ; Saved DE register pair\r
+BC:    DS      2               ; Saved BC register pair\r
+PSW:   DS      2               ; Saved PSW (A + CC)\r
+SP:    DS      2               ; Saved Stack Pointer\r
+PC:    DS      2               ; Saved Program Counter\r
+OFLAG: DS      1               ; Output suspended flag\r
+TFLAG: DS      1               ; Flag to enable TRACING\r
+SFLAG: DS      1               ; Flag to enable SUBROUTINE tracing\r
+AFLAG: DS      1               ; Flag to enable AUTO REGISTER DISPLAY\r
+BRKTAB:        DS      24              ; Breakpoint table\r
+INST:  DS      6               ; Save area for "faking" instructions\r
+BUFFER:        DS      48              ; Input/temp buffer & stack\r
+DSTACK EQU     $&0FFFFh        ; Debugger stack\r
+;\r
+; Startup code... Kick off the monitor\r
+;\r
+       ORG     ROM             ; Debugger code goes here\r
+;\r
+       LXI     SP,DSTACK       ; Set up initial stack pointer\r
+       JMP     TEST            ; Execute main program\r
+       DS      2               ; Filler bytes to first int\r
+;\r
+; Interrupt handlers for RESTART interrupts\r
+;\r
+; Although they RST 1.5, 2.5 and 3.5 vectors are not used by the\r
+; 8085 hardware,  they are included since the space must contain\r
+; SOMETHING,  and who knows,  perhaps someone uses them for jump\r
+; table addresses etc...\r
+;\r
+; Restart 1 is the entry point for breakpoints\r
+RST1:  JMP     ENTRY           ; Execute handler\r
+       DS      1               ; Filler to next int\r
+RST15: CALL    RSTINT          ; Invoke interrupt\r
+       DB      12              ; Offset to handler\r
+RST2:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      16              ; Offset to handler\r
+RST25: CALL    RSTINT          ; Invoke interrupt\r
+       DB      20              ; Offset to handler\r
+RST3:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      24              ; Offset to handler\r
+RST35: CALL    RSTINT          ; Invoke interrupt\r
+       DB      28              ; Offset to handler\r
+RST4:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      32              ; Offset to handler\r
+TRAP:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      36              ; Offset to handler\r
+RST5:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      40              ; Offset to handler\r
+RST55: CALL    RSTINT          ; Invoke interrupt\r
+       DB      44              ; Offset to handler\r
+RST6:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      48              ; Offset to handler\r
+RST65: CALL    RSTINT          ; Invoke interrupt\r
+       DB      52              ; Offset to handler\r
+RST7:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      56              ; Offset to handler\r
+RST75: CALL    RSTINT          ; Invoke interrupt\r
+       DB      60              ; Offset to handler\r
+RST8:  CALL    RSTINT          ; Invoke interrupt\r
+       DB      64              ; Offset to handler\r
+;\r
+; Process a RESTART interrupt, get offset & vector to code\r
+; To speed processing, it is assumed that the user program\r
+; base address begins on a 256 byte page boundary.\r
+;\r
+RSTINT:        XTHL                    ; Save HL, Get PTR to offset\r
+       PUSH    PSW             ; Save A and CC\r
+       MOV     A,M             ; Get offset\r
+       LHLD    UBASE           ; Get high of user program\r
+       MOV     L,A             ; Set low address\r
+       POP     PSW             ; Restore A & CC\r
+       XTHL                    ; Restore HL, set \r
+       RET                     ; Vector to interrupt\r
+;\r
+; Register -> text translation tables used by the disassembler. These tables\r
+; go here (near beginning) so that we can be sure the high address will not\r
+; cross a page boundary allowing us to index by modifying low address only.\r
+;\r
+RTAB:  DB      "BCDEHLMA"      ; Table of register names\r
+RPTAB: DB      "BDHS"          ; Table of register pairs\r
+;\r
+; Entry point for breakpoints & program tracing\r
+;\r
+; Save the user program registers\r
+ENTRY: SHLD    HL              ; Save HL\r
+       XCHG                    ; Get DE\r
+       SHLD    DE              ; Save DE\r
+       POP     H               ; Get RET addrss\r
+       SHLD    PC              ; Save PC\r
+       PUSH    B               ; Copy BC\r
+       POP     H               ; And get it\r
+       SHLD    BC              ; Save PC\r
+       PUSH    PSW             ; Copy PSW\r
+       POP     H               ; And get it\r
+       SHLD    PSW             ; Save PSW\r
+       LXI     H,0             ; Start with zero\r
+       DAD     SP              ; Get SP\r
+       SHLD    SP              ; Save SP\r
+       LXI     SP,DSTACK       ; Move to our stack\r
+       LHLD    PC              ; Get RET addrss\r
+       DCX     H               ; Backup to actual instruction\r
+       SHLD    PC              ; Save PC\r
+       LXI     D,BRKTAB        ; Point to breakpoint table\r
+       MVI     B,'0'           ; Assume breakpoint #0\r
+; Search breakpoint table & see if this is a breakpoint\r
+TRYBRK:        LDAX    D               ; Get HIGH byte from table\r
+       INX     D               ; Advance\r
+       CMP     H               ; Does it match?\r
+       LDAX    D               ; Get LOW byte from table\r
+       INX     D               ; Advance\r
+       JNZ     NOTBRK          ; No, try next\r
+       CMP     L               ; Does it match?\r
+       JZ      FOUND           ; Yes, we have an entry\r
+NOTBRK:        INX     D               ; Skip saved code byte\r
+       INR     B               ; Advance breakpoint number\r
+       MOV     A,B             ; Get breakpoint number\r
+       CPI     '0'+8           ; Table exausted\r
+       JC      TRYBRK          ; No, keep looking\r
+; This interrupt is NOT a breakpoint\r
+       JMP     NOBK            ; Enter with no breakpoint\r
+; This interrupt is a breakpoint, display the message\r
+FOUND: CALL    PRTMSG          ; Output message\r
+       DB      "** Breakpoint ",0\r
+       MOV     A,B             ; Get breakpoint number\r
+       CALL    OUT             ; Output it\r
+       CALL    CRLF            ; New line\r
+; Reenter monitor, first, restore all breakpoint opcodes\r
+NOBK:  LXI     H,BRKTAB        ; Point to breakpoint table\r
+       MVI     B,8             ; 8 breakpoints\r
+FIXL:  MOV     D,M             ; Get HIGH address\r
+       INX     H               ; Advance\r
+       MOV     E,M             ; Get LOW address\r
+       INX     H               ; Advance\r
+       MOV     A,D             ; Get high\r
+       ORA     E               ; Test for ZERO\r
+       JZ      NOFIX           ; Breakpoint is not set\r
+       MOV     A,M             ; Get opcode\r
+       STAX    D               ; And patch user code\r
+NOFIX: INX     H               ; Skip opcode\r
+       DCR     B               ; Reduce count\r
+       JNZ     FIXL            ; Not finished, keep going\r
+       LDA     TFLAG           ; Get trace mode flag\r
+       ANA     A               ; Is it enabled?\r
+       JNZ     TRTB            ; Yes, enter trace mode\r
+       LDA     AFLAG           ; Get auto register display flag\r
+       ANA     A               ; Is it enabled?\r
+       CNZ     REGDIS          ; Yes, display the registers\r
+       JMP     REST            ; Enter monitor\r
+; Prompt for and handle trace mode commands\r
+TRTB:  CALL    PRTMSG          ; Output message\r
+       DB      "T> ",0         ; Trace mode prompt\r
+       LHLD    PC              ; Get PC\r
+       XCHG                    ; Move to DE\r
+       CALL    DINST           ; Disassemble the instruction\r
+       CALL    CRLF            ; New line\r
+       LDA     AFLAG           ; Get auto register display flag\r
+       ANA     A               ; Is it enabled?\r
+       CNZ     REGDIS          ; Yes, display the registers\r
+TRL:   CALL    INCHR           ; Get a command character\r
+       CPI     ' '             ; Execute command?\r
+       JZ      NOADR           ; Yes, handle it\r
+       CPI     1Bh             ; ESCAPE?\r
+       JZ      RECR            ; Yes, abort\r
+       CPI     '?'             ; Register display?\r
+       JNZ     TRL             ; No, ignore it\r
+       CALL    REGDIS          ; Display the registers\r
+       JMP     TRTB            ; And go again\r
+;\r
+; Main entry point for the 8080 debugger\r
+;\r
+TEST:  CALL    INIT            ; Set up hardware\r
+       CALL    PRTMSG          ; Output herald message\r
+       DB      0Dh,0Ah\r
+       DB      "MON85 Version 1.2"\r
+       DB      0Dh,0Ah,0Ah\r
+       DB      "Copyright 1979-2007 Dave Dunfield"\r
+       DB      0Dh,0Ah\r
+       DB      "2012 Roman Borik"\r
+       DB      0Dh,0Ah\r
+       DB      "All rights reserved."\r
+       DB      0Ah,0\r
+       LXI     H,UBASE         ; Point to start of reserved RAM\r
+       MVI     C,(DSTACK-UBASE)&0FFh ; Number of bytes to zero\r
+INIL1: MVI     M,0             ; Clear a byte\r
+       INX     H               ; Advance\r
+       DCR     C               ; Reduce count\r
+       JNZ     INIL1           ; Clear em all\r
+       LXI     H,0FFFFh        ; Set flags\r
+       SHLD    SFLAG           ; Turn on SUBTRACE & AUTOREG\r
+       LXI     H,UBASE         ; Default user stack (below monitor RAM)\r
+       SHLD    SP              ; Set user SP\r
+; Newline and prompt for command\r
+RECR:  CALL    CRLF            ; Output a newline\r
+; Prompt for an input command\r
+REST:  LXI     SP,DSTACK       ; Reset stack pointer\r
+       CALL    PRTMSG          ; Output message\r
+       DB      "C> ",0         ; Command prompt\r
+       CALL    INPT            ; Get command character\r
+; Look up command in table\r
+       MOV     B,A             ; Save for later\r
+       LXI     H,CTABLE        ; Point to command table\r
+REST1: MOV     A,M             ; Get char\r
+       INX     H               ; Advance\r
+       CMP     B               ; Do it match?\r
+       JZ      REST2           ; Yes, go for it\r
+       INX     H               ; Skip HIGH address\r
+       INX     H               ; Skip LOW address\r
+       ANA     A               ; end of table?\r
+       JNZ     REST1           ; Its OK\r
+; Error has occured, issue message & return for command\r
+ERROR: MVI     A,'?'           ; Error indicator\r
+       CALL    OUT             ; Display\r
+       JMP     RECR            ; And wait for command\r
+; We have command, execute it\r
+REST2: INX     D               ; Skip command character\r
+       MOV     A,M             ; Get low address\r
+       INX     H               ; Skip to next\r
+       MOV     H,M             ; Get HIGH address\r
+       MOV     L,A             ; Set LOW\r
+       CALL    SKIP            ; Set 'Z' of no operands\r
+       PCHL                    ; And execute\r
+; Table of commands to execute\r
+CTABLE:        DB      'A'             ; Set AUTOREG flag\r
+       DW      AUTO\r
+       DB      'B'             ; Set/Display breakpoint\r
+       DW      SETBRK\r
+       DB      'C'             ; Copy memory\r
+       DW      COPY\r
+       DB      'D'             ; Disassemble\r
+       DW      GODIS\r
+       DB      'E'             ; Edit memory\r
+       DW      EDIT\r
+       DB      'F'             ; Fill memory\r
+       DW      FILL\r
+       DB      'G'             ; Go (begin execution)\r
+       DW      GO\r
+       DB      'H'             ; Send out memory as Intel HEX\r
+       DW      SNDHEX\r
+       DB      'I'             ; Input from port\r
+       DW      INPUT\r
+       DB      'L'             ; Load from serial port\r
+       DW      LOAD\r
+       DB      'M'             ; Memory display\r
+       DW      MEMRY\r
+       DB      'O'             ; Output to port\r
+       DW      OUTPUT\r
+       DB      'R'             ; Set/Display Registers\r
+       DW      REGIST\r
+       DB      'S'             ; Set SUBTRACE flag\r
+       DW      SUBON\r
+       DB      'T'             ; Set TRACE mode\r
+       DW      TRACE\r
+       DB      'U'             ; Set/Display user base\r
+       DW      USRBASE\r
+       DB      '?'             ; Help command\r
+       DW      HELP\r
+       DB      0               ; End of table\r
+       DW      REST            ; Handle NULL command\r
+;\r
+; Help command\r
+;\r
+HELP:  LXI     H,HTEXT         ; Point to help text\r
+       SUB     A               ; Get a zero\r
+       STA     OFLAG           ; Clear the output flag\r
+; Output each line\r
+HELP1: MVI     C,25            ; Column counter\r
+HELP2: MOV     A,M             ; Get character\r
+       INX     H               ; Advance to next\r
+       ANA     A               ; End of line?\r
+       JZ      HELP4           ; Yes, terminate\r
+       CPI     '!'             ; Separator?\r
+       JZ      HELP3           ; Yes, output\r
+       CALL    OUT             ; Write character\r
+       DCR     C               ; Reduce count\r
+       JMP     HELP2           ; Keep going\r
+; Fill with spaces to discription column\r
+HELP3: CALL    SPACE           ; Output a space\r
+       DCR     C               ; Reduce count\r
+       JNZ     HELP3           ; Do them all\r
+       MVI     A,'-'           ; Spperator\r
+       CALL    OUT             ; Display\r
+       CALL    SPACE           ; And space over\r
+       JMP     HELP2           ; Output rest of line\r
+; End of line encountered...\r
+HELP4: CALL    CHKSUS          ; New line\r
+       MOV     A,M             ; Get next byte\r
+       ANA     A               ; End of text?\r
+       JNZ     HELP1           ; Do them all\r
+       JMP     RECR            ; And go home\r
+;\r
+; Input from port\r
+;\r
+INPUT: CALL    CALC8           ; Get port number\r
+       MVI     A,0DBh          ; 'IN' instruction\r
+       MVI     H,0C9h          ; 'RET' instruction\r
+       STA     INST            ; Set RAM instruction\r
+       SHLD    INST+1          ; Set RAM instruction\r
+       CALL    PRTMSG          ; Output message\r
+       DB      "DATA=",0\r
+       CALL    INST            ; Perform the read\r
+       CALL    HPR             ; Output it\r
+       JMP     RECR            ; Newline & EXIT\r
+;\r
+; Output to port\r
+;\r
+OUTPUT:        CALL    CALC8           ; Get port number\r
+       MVI     A,0D3h          ; 'OUT' instruction\r
+       MVI     H,0C9h          ; 'RET' instruction\r
+       STA     INST            ; Set RAM instruction\r
+       SHLD    INST+1          ; Set RAM instruction\r
+       CALL    CALC8           ; Get data byte\r
+       CALL    INST            ; Output the data\r
+       JMP     REST            ; Back to command prompt\r
+;\r
+; Set breakpoint command\r
+;\r
+SETBRK:        JZ      DISBRK          ; No operands, display breakpoints\r
+; Set a breakpoint\r
+       CALL    CALC8           ; Get hex operand\r
+       CPI     8               ; In range?\r
+       JNC     ERROR           ; No, invalud\r
+       LXI     H,BRKTAB-3      ; Point to breakpoint table\r
+       LXI     B,3             ; Offset for a breakpoint\r
+SBRLP: DAD     B               ; Advance to next breakpoint\r
+       DCR     A               ; Reduce count\r
+       JP      SBRLP           ; Go until we are there\r
+       PUSH    H               ; Save table address\r
+       CALL    CALC            ; Get address\r
+       POP     D               ; Restore address\r
+       XCHG                    ; D=brkpt address, H=table address\r
+       MOV     M,D             ; Set HIGH address in table\r
+       INX     H               ; Advance\r
+       MOV     M,E             ; Set LOW address in table\r
+       INX     H               ; Advance\r
+       LDAX    D               ; Get opcode from memory\r
+       MOV     M,A             ; Save in table\r
+       JMP     REST            ; And get next command\r
+; Display breakpoints\r
+DISBRK:        LXI     D,BRKTAB        ; Point to breakpoint table\r
+       MVI     B,'0'           ; Begin with breakpoint zero\r
+DISLP: MVI     A,'B'           ; Lead in character\r
+       CALL    OUT             ; Output\r
+       MOV     A,B             ; Get breakpoint number\r
+       CALL    OUT             ; Output\r
+       MVI     A,'='           ; Seperator character\r
+       CALL    OUT             ; Output\r
+       LDAX    D               ; Get HIGH address\r
+       MOV     H,A             ; Copy\r
+       INX     D               ; Advance\r
+       LDAX    D               ; Get LOW address\r
+       MOV     L,A             ; Copy\r
+       ORA     H               ; Is breakpoint set?\r
+       JZ      NOTSET          ; No, don't display\r
+       CALL    HLOUT           ; Output in hex\r
+       JMP     GIVLF           ; And proceed\r
+; Breakpoint is not set\r
+NOTSET:        CALL    PRTMSG          ; Output message\r
+       DB      "****",0        ; Indicate not set\r
+GIVLF: MVI     A,' '           ; Get a space\r
+       CALL    OUT             ; Output\r
+       CALL    OUT             ; Output\r
+       MOV     A,B             ; Get breakpoint address\r
+       CPI     '0'+3           ; Halfway through?\r
+       CZ      CRLF            ; Yes, new line\r
+       INX     D               ; Skip low byte\r
+       INX     D               ; Skip opcode\r
+       INR     B               ; Advance breakpoint number\r
+       MOV     A,B             ; Get number again\r
+       CPI     '0'+8           ; All done?\r
+       JC      DISLP           ; No, keep going\r
+       CALL    CRLF            ; New line\r
+       LXI     H,AUTMSG        ; Message for AFLAG\r
+       LDA     AFLAG           ; Get flag state\r
+       CALL    DISON           ; Display ON/OFF indication\r
+       LXI     H,SUBMSG        ; Message for SFLAG\r
+       LDA     SFLAG           ; Get flag state\r
+       CALL    DISON           ; Display ON/OFF indication\r
+       LXI     H,TRCMSG        ; Message for TFLAG\r
+       LDA     TFLAG           ; Get flag state\r
+       CALL    DISON           ; Display ON/OFF indication\r
+       CALL    CRLF            ; New line\r
+       JMP     REST            ; Back for another command\r
+; Display ON/OFF flag state\r
+DISON: PUSH    PSW             ; Save A\r
+       CALL    PRTSTR          ; Output message\r
+       POP     PSW             ; Restore A\r
+       LXI     H,OFF           ; Assume OFF\r
+       ANA     A               ; Test A\r
+       JZ      PRTSTR          ; Yes, display OFF\r
+       LXI     H,ON            ; Convert to ON\r
+       JMP     PRTSTR          ; And display ON\r
+;\r
+; GO command, Begin program execution\r
+;\r
+GO:    JZ      NOHEX           ; Address not given, assume default\r
+       CALL    CALC            ; Get argument\r
+       SHLD    PC              ; Save new PC value\r
+NOHEX: LDA     TFLAG           ; Get trace flag\r
+       ANA     A               ; Enabled?\r
+       JNZ     TRTB            ; Yes, wait for prompt\r
+; Single-step one instruction...\r
+; Used for first instruction even when NOT tracing, so\r
+; that we can insert breakpoints\r
+NOADR: SUB     A               ; Get NOP\r
+       MOV     H,A             ; Set high\r
+       MOV     L,A             ; Set LOW\r
+       STA     INST            ; Set first byte\r
+       SHLD    INST+1          ; Set second & third\r
+       LHLD    PC              ; Get PC\r
+       XCHG                    ; Set DE to PC\r
+       CALL    LOOK            ; Lookup instruction\r
+       MOV     B,A             ; Save the TYPE/LENGTH byte\r
+       ANI     03h             ; Mask TYPE, save LENGTH\r
+       MOV     C,A             ; Save for count\r
+; Copy instruction into "faking" area\r
+       LXI     H,INST          ; Point to saved instruction\r
+GOSET: LDAX    D               ; Get byte from code\r
+       MOV     M,A             ; Save in instruction\r
+       INX     H               ; Advance output\r
+       INX     D               ; Advance input\r
+       DCR     C               ; Reduce count\r
+       JNZ     GOSET           ; Copy it all\r
+       XCHG                    ; HL = addrss to execute\r
+       MVI     A,0C3h          ; Get a JMP instruction\r
+       STA     INST+3          ; Set up a JUMP instruction\r
+       SHLD    INST+4          ; Set target address\r
+       LDA     TFLAG           ; Get trace flag\r
+       ANA     A               ; Are we tracing?\r
+       JZ      NOTRC           ; No, we are not\r
+       PUSH    B               ; Save TYPE/LENGTH\r
+       LHLD    INST+4          ; Get termination address\r
+       INX     H               ; Skip this one\r
+       SHLD    BUFFER          ; Save for "fake" handling\r
+       LXI     H,FAKE          ; Point to FAKE routine\r
+       SHLD    INST+4          ; Save new addres\r
+       POP     B               ; Restore TYPE/LENGTH\r
+; Simulate any control transfer instruction\r
+       LDA     INST            ; Get instruction\r
+       CPI     0E9h            ; Is it PCHL?\r
+       JNZ     NOPCHL          ; No, skip\r
+       LHLD    HL              ; Get user HL value\r
+       JMP     HLJMP           ; And simulate a jump\r
+NOPCHL:        CPI     0CBh            ; Is it RSTV?\r
+       JNZ     NORSTV          ; No, skip\r
+       LDA     PSW             ; Get status flags\r
+       ANI     2               ; Check V flag\r
+       JNZ     NOTRC           ; Is set, execute instruction\r
+       STA     INST            ; Change to NOP\r
+       JMP     NOTRC           ; Not set, execute NOP\r
+NORSTV:        CPI     0DDh            ; Is it JNK?\r
+       JZ      JNKJK           ; Yes, go\r
+       CPI     0FDh            ; Is it JK?\r
+       JNZ     NOJNK           ; No, skip\r
+JNKJK: ANI     20h             ; Save K flag from instruction code\r
+       MOV     C,A\r
+       LDA     PSW             ; Get status flags\r
+       ANI     20h             ; Save only K flag\r
+       XRA     C               ; Compare them\r
+       JZ      NOPSH           ; If they are equal, make jump\r
+       JMP     NOTRC           ; No jump \r
+NOJNK: MOV     A,B             ; Get TYPE back\r
+       CPI     0Bh             ; Is it a 'JUMP'\r
+       JZ      GOJMP           ; Yes, handle it\r
+       CPI     05h             ; Is it a 'RETURN'\r
+       JZ      CALRET          ; Yes, handle it\r
+       ANI     0F8h            ; Save only conditional bits\r
+       JZ      NOTRC           ; Not conditional, always execute instruction\r
+       ANI     08h             ; Does this test require COMPLEMENTED flags\r
+       LDA     PSW             ; Get status flags\r
+       JZ      NOCOM           ; No need to complement\r
+       CMA                     ; Invert for NOT tests\r
+NOCOM: MOV     C,A             ; Save PSW bits\r
+       MOV     A,B             ; Get conditon back\r
+       RAL                     ; Is it SIGN flag?\r
+       JC      SIGN            ; Yes, handle it\r
+       RAL                     ; Is it ZERO flag?\r
+       JC      ZERO            ; Yes, handle it\r
+       RAL                     ; Is it PARITY flag?\r
+       JC      PARITY          ; Yes, handle it\r
+; This instruction is conditional on the CARRY flag\r
+CARRY: MOV     A,C             ; Get flag bits\r
+       ANI     01h             ; Test CARRY flag\r
+       JMP     ENFLG           ; And proceed\r
+; This instruction is conditional on the SIGN flag\r
+SIGN:  MOV     A,C             ; Get flag bits\r
+       ANI     80h             ; Test SIGN flag\r
+       JMP     ENFLG           ; And proceed\r
+; This instruction is conditional on the ZERO flag\r
+ZERO:  MOV     A,C             ; Get flag bits\r
+       ANI     40h             ; Test ZERO flag\r
+       JMP     ENFLG           ; And proceed\r
+; This instruction is conditional on the PARITY flag\r
+PARITY:        MOV     A,C             ; Get flag bits\r
+       ANI     04h             ; Test PARITY flag\r
+; Execute conditional instruction\r
+ENFLG: JZ      NOTRC           ; Not executed\r
+       MOV     A,B             ; Get type back\r
+       ANI     04h             ; Is it JUMP\r
+       JNZ     CALRET          ; No, try next\r
+; Simulate a JUMP instruction\r
+GOJMP: LDA     INST            ; Get instruction\r
+       CPI     0CDh            ; Is it a CALL\r
+       JZ      PADR            ; Yes\r
+       ANI     0C7h            ; Mask conditional\r
+       CPI     0C4h            ; Conditional call?\r
+       JNZ     NOPSH           ; No, its a jump\r
+; Simulate a subroutine trace\r
+PADR:  LDA     SFLAG           ; Get subroutine tracing flag\r
+       ANA     A               ; Is it set?\r
+       JZ      NOTRC           ; No, simulate as one instruction\r
+       LHLD    BUFFER          ; Get termination address\r
+       DCX     H               ; Backup\r
+       XCHG                    ; D = address\r
+       LHLD    SP              ; Get user SP\r
+       DCX     H               ; Backup\r
+       MOV     M,D             ; Set HIGH return address\r
+       DCX     H               ; Backup\r
+       MOV     M,E             ; Set LOW return address\r
+       SHLD    SP              ; Resave user SP\r
+; Continue simulation of a JUMP type instruction\r
+NOPSH: LHLD    INST+1          ; Get target address\r
+       JMP     HLJMP           ; And proceed\r
+; Handle simulation of RETURN instruction\r
+CALRET:        LHLD    SP              ; Get sser SP\r
+       MOV     E,M             ; Get LOW return address\r
+       INX     H               ; Advance\r
+       MOV     D,M             ; Get HIGH return address\r
+       INX     H               ; Advance\r
+       SHLD    SP              ; Resave user SP\r
+       XCHG                    ; Set HL = address\r
+; Simulate a jump to the address in HL\r
+HLJMP: INX     H               ; Advance\r
+       SHLD    BUFFER          ; Save new target address\r
+       SUB     A               ; Get NOP\r
+       MOV     H,A             ; Set HIGH\r
+       MOV     L,A             ; Set LOW\r
+       STA     INST            ; NOP first byte\r
+       SHLD    INST+1          ; NOP second byte\r
+; Dispatch the user program\r
+; First, insert any breakpoints into the object code\r
+NOTRC: LXI     D,BRKTAB        ; Point to breakpoint table\r
+       MVI     C,8             ; Size of table (in entries)\r
+RESBP: LDAX    D               ; Get a HIGH address\r
+       MOV     H,A             ; Save for later\r
+       INX     D               ; Advance\r
+       LDAX    D               ; Get low address\r
+       MOV     L,A             ; Save for later\r
+       INX     D               ; Advance\r
+       ORA     H               ; Is breakpoint enabled?\r
+       JZ      NORES           ; No, its not\r
+       MVI     M,0CFh          ; Set up a RST 1 breakpoint\r
+NORES: INX     D               ; Skip opcode\r
+       DCR     C               ; Reduce count\r
+       JNZ     RESBP           ; Do them all\r
+; Restore the user applications registers\r
+       LHLD    SP              ; Get stack pointer\r
+       SPHL                    ; Set stack pointer\r
+       LHLD    BC              ; Get BC\r
+       PUSH    H               ; Save\r
+       POP     B               ; And set\r
+       LHLD    PSW             ; Get PSW\r
+       PUSH    H               ; Save\r
+       POP     PSW             ; And set\r
+       LHLD    DE              ; Get DE\r
+       XCHG                    ; Set DE\r
+       LHLD    HL              ; Get HL\r
+       JMP     INST            ; Execute "faked" instruction\r
+; Trace routine: simulate a breakpoint interrupt\r
+FAKE:  PUSH    H               ; Save HL on stack\r
+       LHLD    BUFFER          ; Get address to execute\r
+       XTHL                    ; Restore HL, [SP] = address\r
+       JMP     ENTRY           ; Display the registers\r
+;\r
+; Display/Change registers\r
+;\r
+REGIST:        JNZ     CHG1            ; Register name to change is given\r
+; Display registers\r
+       CALL    REGDIS          ; Display registers\r
+       JMP     REST            ; And exit\r
+; Set register value\r
+CHG1:  MOV     B,A             ; Save first register name char\r
+       CALL    GETCHI          ; Get char (in upper case)\r
+       MOV     C,A             ; Save for later\r
+       JZ      OKCH            ; End of string\r
+; Drop extra characters incase 'PSW'\r
+CHG2:  CALL    GETCHR          ; Get next\r
+       JNZ     CHG2            ; Clean them out\r
+; Get new value for register\r
+OKCH:  CALL    CALC            ; Get new value\r
+       MOV     A,B             ; Get first char\r
+       CPI     'H'             ; Is it HL pair\r
+       JNZ     CDE             ; No, try next\r
+       SHLD    HL              ; Set HL value\r
+       JMP     REST            ; And proceed\r
+CDE:   CPI     'D'             ; Is it DE pair?\r
+       JNZ     CBC             ; No, try next\r
+       SHLD    DE              ; Set DE value\r
+       JMP     REST            ; And proceed\r
+CBC:   CPI     'B'             ; Is it BC pair?\r
+       JNZ     CSP             ; No, try next\r
+       SHLD    BC              ; Set BC value\r
+       JMP     REST            ; And proceed\r
+CSP:   CPI     'S'             ; Is it SP?\r
+       JNZ     CP              ; No, try next\r
+       SHLD    SP              ; Set SP value\r
+       JMP     REST            ; And proceed\r
+CP:    CPI     'P'             ; Is it PS or PC\r
+       JNZ     ERROR           ; No, error\r
+       MOV     A,C             ; Get low character\r
+       CPI     'S'             ; Is it PSW?\r
+       JNZ     CPC             ; No, try next\r
+       SHLD    PSW             ; Set new PSW\r
+       JMP     REST            ; And proceed\r
+CPC:   CPI     'C'             ; Is it PC?\r
+       JNZ     ERROR           ; No, error\r
+       SHLD    PC              ; Set new PC\r
+       JMP     REST            ; And proceed\r
+; Process an ON/OFF operand\r
+ONOFF: CALL    SKIP            ; Get next char\r
+       CPI     'O'             ; Must begin with ON\r
+       JNZ     ERROR           ; Invalid\r
+       CALL    GETCHI          ; Get next char\r
+       MVI     B,0             ; Assume OFF\r
+       CPI     'F'             ; OFF?\r
+       JZ      RETON           ; Yes, set it\r
+       CPI     'N'             ; ON?\r
+       JNZ     ERROR           ; No, error\r
+       DCR     B               ; Convert to FF\r
+RETON: MOV     A,B             ; Save new value\r
+       RET\r
+;\r
+; Turn automatic register display ON or OFF\r
+;\r
+AUTO:  CALL    ONOFF           ; Get ON/OFF value\r
+       STA     AFLAG           ; Set AUTOREG flag\r
+       JMP     REST            ; And proceed\r
+;\r
+; Turn SUBROUTINE tracing ON or OFF\r
+;\r
+SUBON: CALL    ONOFF           ; Get ON/OFF value\r
+       STA     SFLAG           ; Set SUBTRACE flag\r
+       JMP     REST            ; And proceed\r
+;\r
+; Set TRACE mode ON or OFF\r
+;\r
+TRACE: CALL    ONOFF           ; Get ON/OFF value\r
+       STA     TFLAG           ; Set TRACE flag\r
+       JMP     REST            ; And proceed\r
+;\r
+; Edit memory contents\r
+;\r
+EDIT:  CALL    CALC            ; Get address\r
+EDIT1: CALL    HLOUT           ; Display address\r
+       CALL    SPACE           ; Separator\r
+       MOV     A,M             ; Get contents\r
+       CALL    HPR             ; Output\r
+       MVI     A,'='           ; Prompt\r
+       CALL    OUT             ; Output\r
+       PUSH    H               ; Save address\r
+       CALL    INPT            ; Get a value\r
+       POP     H               ; Restore address\r
+       INX     H               ; Assume advance\r
+       JZ      EDIT1           ; Null, advance\r
+       DCX     H               ; Fix mistake\r
+       DCX     H               ; Assume backup\r
+       CPI     '-'             ; Backup?\r
+       JZ      EDIT1           ; Yes, backup a byte\r
+       INX     H               ; Fix mistake\r
+       CPI     27h             ; Single quote?\r
+       JNZ     EDIT3           ; No, try hex value\r
+; Handle quoted ASCII text\r
+       INX     D               ; Skip the quote\r
+EDIT2: LDAX    D               ; Get char\r
+       INX     D               ; Advance input\r
+       ANA     A               ; End of loop?\r
+       JZ      EDIT1           ; Yes, exit\r
+       MOV     M,A             ; Save it\r
+       INX     H               ; Advance output\r
+       JMP     EDIT2           ; And proceed\r
+; Handle HEXIDECIMAL values\r
+EDIT3: PUSH    H               ; Save address\r
+       CALL    CALC8           ; Get HEX value\r
+       POP     H               ; HL = address\r
+       MOV     M,A             ; Set value\r
+       INX     H               ; Advance to next\r
+       CALL    SKIP            ; More operands?\r
+       JNZ     EDIT3           ; Get then all\r
+       JMP     EDIT1           ; And continue\r
+;\r
+; FIll memory with a value\r
+;\r
+FILL:  CALL    CALC            ; Get starting address\r
+       PUSH    H               ; Save for later\r
+       CALL    CALC            ; Get ending address\r
+       PUSH    H               ; Save for later\r
+       CALL    CALC8           ; Get value\r
+       MOV     C,A             ; C = value\r
+       POP     D\r
+       INX     D               ; DE = End address+1\r
+       POP     H               ; HL = Starting address\r
+       CALL    COMP16          ; Is Start<End ?\r
+       JNC     ERROR           ; Yes, bad entry\r
+FILL1: MOV     M,C             ; Save one byte\r
+       INX     H               ; Advance\r
+       CALL    COMP16          ; Test for match\r
+       JC      FILL1           ; And proceed\r
+       JMP     REST            ; Back for next\r
+;\r
+; 16 bit compare of HL to DE\r
+;\r
+COMP16:        MOV     A,H             ; Get HIGH\r
+       CMP     D               ; Match?\r
+       RNZ                     ; No, we are done\r
+       MOV     A,L             ; Get LOW\r
+       CMP     E               ; Match?\r
+       RET\r
+;\r
+; Copy a block of memory\r
+;\r
+COPY:  CALL    CALC            ; Get SOURCE address\r
+       PUSH    H               ; Save for later\r
+       CALL    CALC            ; Get DEST Address\r
+       PUSH    H               ; Save for later\r
+       CALL    CALC            ; Get size\r
+       MOV     B,H             ; BC = Size\r
+       MOV     C,L\r
+       POP     D               ; DE = Dest address\r
+       POP     H               ; HL = Source\r
+       MOV     A,B             ; Size is zero?\r
+       ORA     C\r
+       JZ      REST            ; Yes, exit\r
+       CALL    COMP16          ; Compare source and destination address\r
+       JC      COPY2           ; Dest > Source, jump\r
+       ; Source > Dest\r
+COPY1: MOV     A,M             ; Get byte from source\r
+       STAX    D               ; Write to dest\r
+       INX     H               ; Advance source\r
+       INX     D               ; Advance dest\r
+       DCX     B               ; Reduce count\r
+       MOV     A,C             ; Count is zero ?\r
+       ORA     B\r
+       JNZ     COPY1           ; No, continue\r
+       JMP     REST\r
+       ; Dest > Source\r
+COPY2: DAD     B               ; Move source and destination address to end\r
+       DCX     H               ; of block\r
+       XCHG\r
+       DAD     B\r
+       DCX     H\r
+COPY3: LDAX    D               ; Get byte from source\r
+       MOV     M,A             ; Write to dest\r
+       DCX     D               ; Decrement source address\r
+       DCX     H               ; Decrement destination address\r
+       DCX     B               ; Reduce count\r
+       MOV     A,C             ; Count is zero ?\r
+       ORA     B\r
+       JNZ     COPY3           ; No, continue\r
+       JMP     REST\r
+;\r
+; Display a block of memory\r
+;\r
+MEMRY: CALL    CALC            ; Get operand\r
+       SUB     A               ; Get a ZERO\r
+       STA     OFLAG           ; Clear output flag\r
+ALOOP: CALL    HLOUT2          ; Display address (in hex) with 2 spaces\r
+       MVI     D,16            ; 16 bytes/line\r
+       PUSH    H               ; Save address\r
+ALP1:  MOV     A,M             ; Get byte\r
+       CALL    HPR             ; Output in hex\r
+       CALL    SPACE           ; Space over\r
+       MOV     A,D             ; Get count\r
+       CPI     9               ; At boundary?\r
+       CZ      SPACE           ; Yes, extra space\r
+       MOV     A,D             ; Get count\r
+       ANI     7               ; Mask for low bits\r
+       CPI     5               ; At boundary?\r
+       CZ      SPACE           ; Extra space\r
+       INX     H               ; Advance address\r
+       DCR     D               ; Reduce count\r
+       JNZ     ALP1            ; Do them all\r
+       MVI     D,4             ; # separating spaces\r
+AL2:   CALL    SPACE           ; Output a space\r
+       DCR     D               ; Reduce count\r
+       JNZ     AL2             ; And proceed\r
+       POP     H\r
+       MVI     D,16            ; 16 chars/display\r
+AL3:   MOV     A,M             ; Get data byte\r
+       CALL    OUTP            ; Display (if printable)\r
+       INX     H               ; Advance to next\r
+       DCR     D               ; Reduce count\r
+       JNZ     AL3             ; Do them all\r
+       CALL    CHKSUS          ; Handle output suspension\r
+       JMP     ALOOP           ; And continue\r
+;\r
+; Perform disassembly to console\r
+;\r
+GODIS: CALL    CALC            ; Get starting address\r
+       PUSH    H               ; Save address\r
+       POP     D               ; Copy to D\r
+       SUB     A               ; Get a zero\r
+       STA     OFLAG           ; Clear output flag\r
+VLOOP: CALL    DINST           ; Display one instruction\r
+       CALL    CHKSUS          ; Handle output\r
+       JMP     VLOOP           ; And proceed\r
+;\r
+; Set/display user base address\r
+;\r
+USRBASE: JNZ   USRB1           ; Address is given, set it\r
+       CALL    PRTMSG          ; Output message\r
+       DB      "BASE=",0\r
+       LHLD    UBASE           ; Get address\r
+       CALL    HLOUT           ; Output\r
+       JMP     RECR            ; New line & exit\r
+USRB1: CALL    CALC            ; Get operand\r
+       SHLD    UBASE           ; Set the address\r
+       JMP     REST            ; and return\r
+;\r
+; Send out as Intel HEX\r
+;\r
+SNDHEX:        CALL    CALC            ; Get start address\r
+       PUSH    H               ; Save for later\r
+       CALL    CALC            ; Get end address\r
+       INX     H               ; HL = end+1\r
+       POP     D               ; DE = start\r
+       CALL    COMP16          ; Check for Start > End\r
+       JC      ERROR           ; Bad entry\r
+       MOV     A,L             ; Compute length\r
+       SUB     E\r
+       MOV     L,A\r
+       MOV     A,H\r
+       SBB     D\r
+       MOV     H,A\r
+       XCHG                    ; HL = start, DE = length\r
+SNDHX1:        MOV     A,D             ; Finish ?\r
+       ORA     E\r
+       JZ      SNDHX3          ; Yes, jump\r
+       MVI     B,16            ; 16 bytes per record\r
+       MOV     A,D             ; Is rest > 16 ?\r
+       ORA     A\r
+       JNZ     SNDHX2          ; No, jump\r
+       MOV     A,E\r
+       CMP     B\r
+       JNC     SNDHX2          ; No, jump\r
+       MOV     B,E             ; Yes, B=rest\r
+SNDHX2:        CALL    SHXRC           ; Send out one record\r
+       JMP     SNDHX1          ; continue\r
+;\r
+SNDHX3:        CALL    PRTMSG\r
+       DB      ":00000001FF",0Dh,0Ah,0\r
+       JMP     REST\r
+;\r
+SHXRC: MVI     A,':'           ; Start record\r
+       CALL    OUT\r
+       MOV     A,B             ; Length\r
+       MOV     C,A             ; Init checksum\r
+       CALL    HPR             ; Output in hex\r
+       MOV     A,H             ; High byte of address \r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; Re-save\r
+       MOV     A,H\r
+       CALL    HPR             ; Output in hex\r
+       MOV     A,L             ; Low byte of address \r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; Re-save\r
+       MOV     A,L\r
+       CALL    HPR             ; Output in hex\r
+       XRA     A               ; Record type\r
+       CALL    HPR\r
+SHXRC1:        MOV     A,M             ; One byte\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; Re-save\r
+       MOV     A,M\r
+       INX     H\r
+       CALL    HPR             ; Output in hex\r
+       DCX     D               ; Decrement main counter\r
+       DCR     B               ; Decrement bytes per record counter\r
+       JNZ     SHXRC1\r
+       MOV     A,C             ; Negate checksum\r
+       CMA\r
+       INR     A\r
+       CALL    HPR             ; Output in hex\r
+       JMP     CRLF\r
+;\r
+; Download command\r
+;\r
+LOAD:  MVI     A,0Fh           ; Get default initial state\r
+       JZ      LOAD1           ; Address not given...\r
+       CALL    CALC            ; Get operand value\r
+       SHLD    BUFFER+3        ; Save for later calulation\r
+       MVI     A,0FFh          ; Set new initial state\r
+; Setup the offset calculator\r
+LOAD1: LXI     H,0             ; Assume no offset\r
+       STA     BUFFER          ; Set mode flag\r
+       SHLD    BUFFER+1        ; Assume offset is ZERO\r
+; Download the records\r
+LOAD2: CALL    DLREC           ; Get a record\r
+       JNZ     DLBAD           ; Report error\r
+       JNC     LOAD2           ; Get them all\r
+       JMP     DLWAIT          ; And back to monitor\r
+; Error in receiving download record\r
+DLBAD: CALL    PRTMSG          ; Output message\r
+       DB      "?Load error"\r
+       DB      0Dh,0Ah,0\r
+; Wait till incoming data stream stops\r
+DLWAIT:        MVI     C,0             ; Initial count\r
+DLWAIT1: CALL  IN              ; Test for input\r
+       ANA     A               ; Any data\r
+       JNZ     DLWAIT          ; Reset count\r
+       DCR     C               ; Reduce counter\r
+       JNZ     DLWAIT1         ; Keep looking\r
+       JMP     REST            ; Back to monitor\r
+;\r
+; Download a record from the serial port\r
+;\r
+DLREC: CALL    INCHR           ; Read a character\r
+       CPI     ':'             ; Start of record?\r
+       JZ      DLINT           ; Download INTEL format\r
+       CPI     'S'             ; Is it MOTOROLA?\r
+       JNZ     DLREC           ; No, keep looking\r
+; Download a MOTOROLA HEX format record\r
+DLMOT: CALL    INCHR           ; Get next character\r
+       CPI     '0'             ; Header record?\r
+       JZ      DLREC           ; Yes, skip it\r
+       CPI     '9'             ; End of file?\r
+       JZ      DLEOF           ; Yes, report EOF\r
+       CPI     '1'             ; Type 1 (code) record\r
+       JNZ     DLERR           ; Report error\r
+       CALL    GETBYT          ; Get length\r
+       MOV     C,A             ; Start checksum\r
+       SUI     3               ; Convert for overhead\r
+       MOV     B,A             ; Save data length\r
+       CALL    GETBYT          ; Get first byte of address\r
+       MOV     H,A             ; Set HIGH address\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; And re-save\r
+       CALL    GETBYT          ; Get next byte of address\r
+       MOV     L,A             ; Set LOW address\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; And re-save\r
+       CALL    SETOFF          ; Handle record offsets\r
+DMOT1: CALL    GETBYT          ; Get a byte of data\r
+       MOV     M,A             ; Save in memory\r
+       INX     H               ; Advance\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; And re-save\r
+       DCR     B               ; Reduce length\r
+       JNZ     DMOT1           ; Keep going\r
+       CALL    GETBYT          ; Get record checksum\r
+       ADD     C               ; Include calculated checksum\r
+       INR     A               ; Adjust for test\r
+       ANA     A               ; Clear carry set Z\r
+       RET\r
+; Download a record in INTEL hex format\r
+DLINT: CALL    GETBYT          ; Get length\r
+       ANA     A               ; End of file?\r
+       JZ      DLEOF           ; Yes, handle it\r
+       MOV     C,A             ; Begin Checksum\r
+       MOV     B,A             ; Record length\r
+       CALL    GETBYT          ; Get HIGH address\r
+       MOV     H,A             ; Set HIGH address\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; Re-save\r
+       CALL    GETBYT          ; Get LOW address\r
+       MOV     L,A             ; Set LOW address\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; Re-save\r
+       CALL    SETOFF          ; Handle record offsets\r
+       CALL    GETBYT          ; Get type byte\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; Re-save\r
+DLINT1:        CALL    GETBYT          ; Get data byte\r
+       MOV     M,A             ; Save in memory\r
+       INX     H               ; Advance to next\r
+       ADD     C               ; Include in checksum\r
+       MOV     C,A             ; Resave checksum\r
+       DCR     B               ; Reduce count\r
+       JNZ     DLINT1          ; Do entire record\r
+       CALL    GETBYT          ; Get record checksum\r
+       ADD     C               ; Add to computed checksum\r
+       ANA     A               ; Clear carry, set Z\r
+       RET\r
+; End of file on download\r
+DLEOF: STC                     ; Set carry, EOF\r
+       RET\r
+;\r
+; Process record offsets for download records\r
+;\r
+SETOFF:        LDA     BUFFER          ; Get flag\r
+       ANA     A               ; Test flag\r
+       JNZ     SETOF1          ; Special case\r
+; Not first record, adjust for offset & proceed\r
+       XCHG                    ; DE = address\r
+       LHLD    BUFFER+1        ; Get offset\r
+       DAD     D               ; HL = address + offset\r
+       RET\r
+; First record, set USER BASE & calculate offset (if any)\r
+SETOF1:        MVI     A,0             ; Get zero (NO CC)\r
+       STA     BUFFER          ; Clear flag\r
+       SHLD    UBASE           ; Set user program base\r
+       RP                      ; No more action\r
+; Calculate record offset to RAM area\r
+       XCHG                    ; DE = address\r
+       LHLD    BUFFER+3        ; Get operand\r
+       MOV     A,L             ; Subtract\r
+       SUB     E               ; Record\r
+       MOV     L,A             ; From\r
+       MOV     A,H             ; Operand\r
+       SBB     D               ; To get\r
+       MOV     H,A             ; Offset\r
+       SHLD    BUFFER+1        ; Set new offset\r
+       DAD     D               ; Get address\r
+       RET\r
+;\r
+; Gets a byte of HEX data from serial port.\r
+;\r
+GETBYT:        CALL    GETNIB          ; Get first nibble\r
+       RLC                     ; Shift into\r
+       RLC                     ; Upper nibble\r
+       RLC                     ; Of result\r
+       RLC                     ; To make room for lower\r
+       MOV     E,A             ; Keep high digit\r
+       CALL    GETNIB          ; Get second digit\r
+       ORA     E               ; Insert high digit\r
+       RET\r
+; GETS A NIBBLE FROM THE TERMINAL (IN ASCII HEX)\r
+GETNIB:        CALL    INCHR           ; Get a character\r
+       SUI     '0'             ; Is it < '0'?\r
+       JC      GETN1           ; Yes, invalid\r
+       CPI     10              ; 0-9?\r
+       RC                      ; Yes, its OK\r
+       SUI     7               ; Convert\r
+       CPI     10              ; 9-A?\r
+       JC      GETN1           ; Yes, invalid\r
+       CPI     16              ; A-F?\r
+       RC                      ; Yes, its OK\r
+GETN1: POP     D               ; Remove GETNIB RET addr\r
+       POP     D               ; Remove GETBYT RET addr\r
+; Error during download record\r
+DLERR: ORI     0FFh            ; Error indicator\r
+       RET\r
+;\r
+; Read an input line from the console\r
+;\r
+INPT:  LXI     H,BUFFER        ; Point to input buffer\r
+INPT1: CALL    INCHR           ; Get a char\r
+       CPI     1Bh             ; ESCAPE?\r
+       JZ      RECR            ; Back for command\r
+       CPI     0Dh             ; Carriage return?\r
+       JZ      INPT4           ; Yes, exit\r
+       MOV     D,A             ; Save for later\r
+; Test for DELETE function\r
+       CPI     7Fh             ; Is it delete?\r
+       JZ      INPT3           ; Yes, it is\r
+       CPI     08h             ; Backspace?\r
+       JZ      INPT3           ; Yes, it is\r
+; Insert character in buffer\r
+       MOV     A,L             ; Get low address\r
+       CPI     (BUFFER&255)+30 ; Beyond end?\r
+       MVI     A,7             ; Assume error\r
+       JZ      INPT2           ; Yes, report error\r
+       MOV     A,D             ; Get char back\r
+       MOV     M,A             ; Save in memory\r
+       INX     H               ; Advance\r
+INPT2: CALL    OUT             ; Echo it\r
+       JMP     INPT1           ; And proceed\r
+; Delete last character from buffer\r
+INPT3: MOV     A,L             ; Get char\r
+       CPI     BUFFER&255      ; At begining\r
+       MVI     A,7             ; Assume error\r
+       JZ      INPT2           ; Report error\r
+       PUSH    H               ; Save H\r
+       CALL    PRTMSG          ; Output message\r
+       DB      8,' ',8,0       ; Wipe away character\r
+       POP     H               ; Restore H\r
+       DCX     H               ; Backup\r
+       JMP     INPT1           ; And proceed\r
+; Terminate the command\r
+INPT4: MVI     M,0             ; Zero terminate\r
+       CALL    CRLF            ; New line\r
+       LXI     D,BUFFER        ; Point to input buffer\r
+; Advance to next non-blank in buffer\r
+SKIP:  LDAX    D               ; Get char from buffer\r
+       INX     D               ; Advance\r
+       CPI     ' '             ; Space?\r
+       JZ      SKIP            ; Yes, keep looking\r
+       DCX     D               ; Backup to it\r
+       JMP     TOCAP           ; And convert to upper\r
+;\r
+; Read next character from command & convert to upper case\r
+;\r
+GETCHI:        INX     D               ; Skip next character\r
+GETCHR:        LDAX    D               ; Get char from command line\r
+       ANA     A               ; End of line?\r
+       RZ                      ; Yes, return with it\r
+       INX     D               ; Advance command pointer\r
+;\r
+; Convert character in A to uppercase, set Z if SPACE or EOL\r
+;\r
+TOCAP: CPI     61h             ; Lower case?\r
+       JC      TOCAP1          ; Yes, its ok\r
+       ANI     5Fh             ; Convert to UPPER\r
+TOCAP1:        CPI     ' '             ; Space\r
+       RZ                      ; Yes, indicate\r
+       ANA     A               ; Set 'Z' if EOL\r
+       RET\r
+;\r
+; Get 8 bit HEX operands to command\r
+;\r
+CALC8: CALL    CALC            ; Get operand\r
+       MOV     A,H             ; High byte must be zero\r
+       ORA     A\r
+       JNZ     ERROR           ; Bad value\r
+       MOV     A,L             ; Value also to A\r
+       RET\r
+;\r
+; Get 16 bit HEX operands to command\r
+;\r
+CALC:  PUSH    B               ; Save B-C\r
+       CALL    SKIP            ; Find start of operand\r
+       LXI     H,0             ; Begin with zero value\r
+       MOV     C,H             ; Clear flag\r
+CALC1: CALL    GETCHR          ; Get next char\r
+       JZ      CALC3           ; End of number\r
+       CALL    VALHEX          ; Is it valid hex?\r
+       JC      ERROR           ; No, report error\r
+       DAD     H               ; HL = HL*2\r
+       DAD     H               ; HL = HL*4\r
+       DAD     H               ; HL = HL*8\r
+       DAD     H               ; HL = HL*16 (Shift over 4 bits)\r
+       SUI     '0'             ; Convert to ASCII\r
+       CPI     10              ; Decimal number?\r
+       JC      CALC2           ; Yes, its ok\r
+       SUI     7               ; Convert to HEX\r
+CALC2: ORA     L               ; Include in final value\r
+       MOV     L,A             ; Resave low bute\r
+       MVI     C,0FFh          ; Set flag & indicate we have char\r
+       JMP     CALC1           ; And continue\r
+; End of input string was found\r
+CALC3: MOV     A,C             ; Get flag\r
+       POP     B               ; Restore B-C\r
+       ANA     A               ; Was there any digits?\r
+       JZ      ERROR           ; No, invalid\r
+       RET\r
+; Test for character in A as valid hex\r
+VALHEX:        CPI     '0'             ; < '0'\r
+       RC                      ; Too low\r
+       CPI     'G'             ; >'F'\r
+       CMC                     ; Set C state\r
+       RC                      ; Too high\r
+       CPI     3Ah             ; <='9'\r
+       CMC                     ; Set C state\r
+       RNC                     ; Yes, its OK\r
+       CPI     'A'             ; Set C if < 'A'\r
+       RET\r
+;\r
+; Display the user process registers\r
+;\r
+REGDIS:        LHLD    BC              ; Get saved BC pair\r
+       LXI     B,'BC'          ; And register names\r
+       CALL    OUTPT           ; Output\r
+       LHLD    DE              ; Get saved DE pair\r
+       LXI     B,'DE'          ; And register names\r
+       CALL    OUTPT           ; Output\r
+       LHLD    HL              ; Get saved HL pair\r
+       LXI     B,'HL'          ; And register names\r
+       CALL    OUTPT           ; Output\r
+       LHLD    SP              ; Get saved SP\r
+       LXI     B,'SP'          ; And register name\r
+       CALL    OUTPT           ; Output\r
+       LHLD    PC              ; Get saved PC\r
+       LXI     B,'PC'          ; And regsiter name\r
+       CALL    OUTPT           ; Output\r
+       CALL    PRTMSG          ; Output message\r
+       DB      " PSW=",0\r
+       LHLD    PSW             ; Get saved PSW\r
+       CALL    HLOUT2          ; Output value (with two spaces)\r
+       CALL    PRTMSG          ; Output\r
+       DB      " FLAGS=",0\r
+       LHLD    PSW-1           ; Get Flags to H\r
+       MVI     B,'S'           ; 'S' flag\r
+       CALL    OUTB            ; Display\r
+       MVI     B,'Z'           ; 'Z' flag\r
+       CALL    OUTB            ; Display\r
+       MVI     B,'K'           ; 'K' flag\r
+       CALL    OUTB            ; Display\r
+       MVI     B,'A'           ; 'A' flag\r
+       CALL    OUTB            ; Display\r
+       MVI     B,'3'           ; 3. bit flag\r
+       CALL    OUTB            ; Display\r
+       MVI     B,'P'           ; 'P' flag\r
+       CALL    OUTB            ; Display\r
+       MVI     B,'V'           ; 'V' flag\r
+       CALL    OUTB            ; Display\r
+       MVI     B,'C'           ; 'C' flag\r
+       CALL    OUTB            ; Display\r
+       JMP     CRLF            ; New line & exit\r
+; Display contents of a register pair\r
+OUTPT: MOV     A,B             ; Get first char of name\r
+       CALL    OUT             ; Output\r
+       MOV     A,C             ; Get second char of name\r
+       CALL    OUT             ; Output\r
+       MVI     A,'='           ; Get separator\r
+       CALL    OUT             ; Output\r
+HLOUT2:        CALL    HLOUT           ; Output value\r
+       CALL    SPACE           ; Output a space\r
+; Display a space on the console\r
+SPACE: MVI     A,' '           ; Get a spave\r
+       JMP     OUT             ; Display it\r
+; Display an individual flag bit B=title, H[7]=bit\r
+OUTB:  DAD     H               ; Shift H[7] into carry\r
+       MVI     A,'-'           ; Dash for not set flag\r
+       JNC     OUT             ; Display dash\r
+       MOV     A,B             ; Get character\r
+       JMP     OUT             ; And display\r
+;\r
+; Display an instruction in disassembly format\r
+;\r
+DINST: PUSH    D               ; Save address\r
+       MOV     A,D             ; Get high value\r
+       CALL    HPR             ; Output\r
+       MOV     A,E             ; Get low address\r
+       CALL    HPR             ; Output\r
+       CALL    SPACE           ; Output a space\r
+       CALL    LOOK            ; Lookup instruction\r
+       ANI     03h             ; Save length\r
+       PUSH    PSW             ; Save length\r
+       PUSH    H               ; Save table address\r
+       MVI     B,4             ; 4 spaces total\r
+       MOV     C,A             ; Save count\r
+       DCX     D               ; Backup address\r
+; Display the opcode bytes in HEX\r
+VLP1:  INX     D               ; Advance\r
+       LDAX    D               ; Get opcode\r
+       CALL    HPR             ; Output in HEX\r
+       CALL    SPACE           ; Separator\r
+       DCR     B               ; Reduce count\r
+       DCR     C               ; Reduce count of opcodes\r
+       JNZ     VLP1            ; Do them all\r
+; Fill in to boundary\r
+VLP2:  CALL    SPACE           ; Space over\r
+       CALL    SPACE           ; Space over\r
+       CALL    SPACE           ; Spave over\r
+       DCR     B               ; Reduce count\r
+       JNZ     VLP2            ; Do them all\r
+; DISPLAY ASCII equivalent of opcodes\r
+       POP     B               ; Restore table address\r
+       POP     PSW             ; Restore type/length\r
+       POP     D               ; Restore instruction address\r
+       PUSH    D               ; Resave\r
+       PUSH    PSW             ; Resave\r
+       MVI     H,8             ; 8 spaces/field\r
+       ANI     0Fh             ; Save only length\r
+       MOV     L,A             ; Save for later\r
+PCHR:  LDAX    D               ; Get byte from opcode\r
+       INX     D               ; Advance\r
+       CALL    OUTP            ; Display (if printable)\r
+       DCR     H               ; Reduce field count\r
+       DCR     L               ; Reduce opcode count\r
+       JNZ     PCHR            ; Do them all\r
+; Space over to instruction address\r
+SPLP:  CALL    SPACE           ; Output a space\r
+       DCR     H               ; Reduce count\r
+       JNZ     SPLP            ; Do them all\r
+       MVI     D,6             ; Field width\r
+VLP3:  LDAX    B               ; Get char from table\r
+       ANA     A               ; End of string?\r
+       JZ      VOUT1           ; Yes, exit\r
+       CALL    OUT             ; Output it\r
+       INX     B               ; Advance to next\r
+       DCR     D               ; reduce count\r
+       CPI     ' '             ; end of name?\r
+       JNZ     VLP3            ; no, keep going\r
+; Fill in name field with spaces\r
+VOUT:  DCR     D               ; reduce count\r
+       JZ      VLP3            ; Keep going\r
+       CALL    SPACE           ; Output a space\r
+       JMP     VOUT            ; And proceed\r
+; Output operands for the instruction\r
+VOUT1: POP     PSW             ; Restore type\r
+       POP     D               ; Restore instruction address\r
+       DCR     A               ; Is it type1?\r
+       JZ      T1              ; Yes, handle it\r
+; Type 2 -  One byte immediate date\r
+T2:    PUSH    PSW             ; Save type\r
+       MVI     A,'$'           ; Get HEX indicator\r
+       CALL    OUT             ; Output\r
+       POP     PSW             ; Restore type\r
+       DCR     A               ; Type 2?\r
+       JNZ     T3              ; No, try next\r
+       INX     D               ; Advance to data\r
+       LDAX    D               ; Get data\r
+       CALL    HPR             ; Output in HEX\r
+; Type 1 - No operand\r
+T1:    INX     D\r
+       RET\r
+; Type 3 - Two bytes immediate data\r
+T3:    INX     D               ; Skip to low   \r
+       INX     D               ; Skip to high\r
+       LDAX    D               ; Get HIGH\r
+       CALL    HPR             ; Output\r
+       DCX     D               ; Backup to low\r
+       LDAX    D               ; Get LOW\r
+       CALL    HPR             ; Output\r
+       INX     D               ; Advance to high\r
+       INX     D\r
+       RET\r
+;\r
+; Look up instruction in table & return TYPE/LENGTH[A], and string[HL]\r
+;\r
+LOOK:  PUSH    D               ; Save DE\r
+       LDAX    D               ; Get opcode\r
+       MOV     B,A             ; Save for later\r
+       LXI     H,ITABLE        ; Point to table\r
+LOOK1: MOV     A,B             ; Get Opcode\r
+       ANA     M               ; Mask\r
+       INX     H               ; Skip mask\r
+       CMP     M               ; Does it match\r
+       INX     H               ; Skip opcode\r
+       JZ      LOOK3           ; Yes, we found it\r
+; This wasn't it, advance to the next\r
+LOOK2: MOV     A,M             ; Get byte\r
+       INX     H               ; Advance to next\r
+       ANA     A               ; End of string?\r
+       JNZ     LOOK2           ; No, keep looking\r
+       JMP     LOOK1           ; And continue\r
+; We found the instruction, copy over the text description\r
+LOOK3: MOV     C,M             ; Save type\r
+       INX     H               ; Skip type\r
+       LXI     D,BUFFER        ; Point to text buffer\r
+LOOK4: MOV     A,M             ; Get char from source\r
+       INX     H               ; Advance to next\r
+; Insert a RESTART vector number\r
+       CPI     'v'             ; Restart vector\r
+       JNZ     LOOK5           ; No, its OK\r
+       MOV     A,B             ; Get opcode\r
+       RRC                     ; Shift it\r
+       RRC                     ; Over\r
+       RRC                     ; To low digit\r
+       ANI     07h             ; Remove trash\r
+       ADI     '0'             ; Convert to digit\r
+       JMP     LOOK10          ; And set the character\r
+; Insert a register pair name\r
+LOOK5: CPI     'p'             ; Register PAIR?\r
+       JNZ     LOOK6           ; No, try next\r
+       MOV     A,B             ; Get opcode\r
+       RRC                     ; Shift\r
+       RRC                     ; Over into\r
+       RRC                     ; Low digit\r
+       RRC                     ; For lookup\r
+       ANI     03h             ; Save only RP\r
+       PUSH    H               ; Save HL\r
+       LXI     H,RPTAB         ; Point to pair table\r
+       JMP     LOOK9           ; And proceed\r
+; Insert destination register name\r
+LOOK6: CPI     'd'             ; Set destination?\r
+       JNZ     LOOK7           ; No, try next\r
+       MOV     A,B             ; Get opcode\r
+       RRC                     ; Shift\r
+       RRC                     ; Into low\r
+       RRC                     ; digit\r
+       JMP     LOOK8           ; And proceed\r
+; Insert source register name\r
+LOOK7: CPI     's'             ; Source register?\r
+       JNZ     LOOK10          ; No, its OK\r
+       MOV     A,B             ; Get opcode\r
+; Lookup a general processor register\r
+LOOK8: ANI     07h             ; Save only source\r
+       PUSH    H               ; Save HL\r
+       LXI     H,RTAB          ; Point to table\r
+; Lookup register in table\r
+LOOK9: ADD     L               ; Offset to value\r
+       MOV     L,A             ; Resave address\r
+       MOV     A,M             ; Get character\r
+       CPI     'S'             ; 'SP' register ?\r
+       JNZ     LOOK9A          ; No, skip\r
+       STAX    D               ; Save 'S'\r
+       INX     D               ; Advance to next\r
+       MVI     A,'P'           ; Character 'P'\r
+LOOK9A:        POP     H               ; Restore HL\r
+; Save character in destination string\r
+LOOK10:        STAX    D               ; Save value\r
+       INX     D               ; Advance to next\r
+       ANA     A               ; End of list?\r
+       JNZ     LOOK4           ; No, keep copying\r
+; End of LIST\r
+       LXI     H,BUFFER        ; Point to description\r
+       MOV     A,C             ; Get length\r
+       POP     D               ; Restore DE\r
+       RET\r
+;\r
+; Opcode disassembly table: MASK, OPCODE, TYPE/LENGTH, STRINGZ\r
+;\r
+ITABLE:        DB      0FFh,0FEh,02h\r
+       DB      "CPI ",0\r
+       DB      0FFh,3Ah,03h\r
+       DB      "LDA ",0\r
+       DB      0FFh,32h,03h\r
+       DB      "STA ",0\r
+       DB      0FFh,2Ah,03h\r
+       DB      "LHLD ",0\r
+       DB      0FFh,22h,03h\r
+       DB      "SHLD ",0\r
+       DB      0FFh,0F5h,01h\r
+       DB      "PUSH PSW",0\r
+       DB      0FFh,0F1h,01h\r
+       DB      "POP PSW",0\r
+       DB      0FFh,27h,01h\r
+       DB      "DAA",0\r
+       DB      0FFh,76h,01h\r
+       DB      "HLT",0\r
+       DB      0FFh,0FBh,01h\r
+       DB      "EI",0\r
+       DB      0FFh,0F3h,01h\r
+       DB      "DI",0\r
+       DB      0FFh,37h,01h\r
+       DB      "STC",0\r
+       DB      0FFh,3Fh,01h\r
+       DB      "CMC",0\r
+       DB      0FFh,2Fh,01h\r
+       DB      "CMA",0\r
+       DB      0FFh,0EBh,01h\r
+       DB      "XCHG",0\r
+       DB      0FFh,0E3h,01h\r
+       DB      "XTHL",0\r
+       DB      0FFh,0F9h,01h\r
+       DB      "SPHL",0\r
+       DB      0FFh,0E9h,01h\r
+       DB      "PCHL",0\r
+       DB      0FFh,0DBh,02h\r
+       DB      "IN ",0\r
+       DB      0FFh,0D3h,02h\r
+       DB      "OUT ",0\r
+       DB      0FFh,07h,01h\r
+       DB      "RLC",0\r
+       DB      0FFh,0Fh,01h\r
+       DB      "RRC",0\r
+       DB      0FFh,17h,01h\r
+       DB      "RAL",0\r
+       DB      0FFh,1Fh,01h\r
+       DB      "RAR",0\r
+       DB      0FFh,0C6h,02h\r
+       DB      "ADI ",0\r
+       DB      0FFh,0CEh,02h\r
+       DB      "ACI ",0\r
+       DB      0FFh,0D6h,02h\r
+       DB      "SUI ",0\r
+       DB      0FFh,0DEh,02h\r
+       DB      "SBI ",0\r
+       DB      0FFh,0E6h,02h\r
+       DB      "ANI ",0\r
+       DB      0FFh,0F6h,02h\r
+       DB      "ORI ",0\r
+       DB      0FFh,0EEh,02h\r
+       DB      "XRI ",0\r
+       DB      0FFh,00h,01h\r
+       DB      "NOP",0\r
+; 8085 specific instructions\r
+       DB      0FFh,20h,01h\r
+       DB      "RIM",0\r
+       DB      0FFh,30h,01h\r
+       DB      "SIM",0\r
+; 8085 undocumented instructions\r
+       DB      0FFh,08h,01h\r
+       DB      "DSUB B",0\r
+       DB      0FFh,10h,01h\r
+       DB      "ARHL",0\r
+       DB      0FFh,18h,01h\r
+       DB      "RDEL",0\r
+       DB      0FFh,28h,02h\r
+       DB      "LDHI ",0\r
+       DB      0FFh,38h,02h\r
+       DB      "LDSI ",0\r
+       DB      0FFh,0CBh,01h\r
+       DB      "RSTV",0\r
+       DB      0FFh,0D9h,01h\r
+       DB      "SHLX D",0\r
+       DB      0FFh,0DDh,03h\r
+       DB      "JNK ",0\r
+       DB      0FFh,0EDh,01h\r
+       DB      "LHLX D",0\r
+       DB      0FFh,0FDh,03h\r
+       DB      "JK ",0\r
+; Jumps, Calls & Returns\r
+       DB      0FFh,0C3h,0Bh\r
+       DB      "JMP ",0\r
+       DB      0FFh,0CAh,43h\r
+       DB      "JZ ",0\r
+       DB      0FFh,0C2h,4Bh\r
+       DB      "JNZ ",0\r
+       DB      0FFh,0DAh,13h\r
+       DB      "JC ",0\r
+       DB      0FFh,0D2h,1Bh\r
+       DB      "JNC ",0\r
+       DB      0FFh,0EAh,23h\r
+       DB      "JPE ",0\r
+       DB      0FFh,0E2h,2Bh\r
+       DB      "JPO ",0\r
+       DB      0FFh,0FAh,83h\r
+       DB      "JM ",0\r
+       DB      0FFh,0F2h,8Bh\r
+       DB      "JP ",0\r
+       DB      0FFh,0CDh,0Bh\r
+       DB      "CALL ",0\r
+       DB      0FFh,0CCh,43h\r
+       DB      "CZ ",0\r
+       DB      0FFh,0C4h,4Bh\r
+       DB      "CNZ ",0\r
+       DB      0FFh,0DCh,13h\r
+       DB      "CC ",0\r
+       DB      0FFh,0D4h,1Bh\r
+       DB      "CNC ",0\r
+       DB      0FFh,0ECh,23h\r
+       DB      "CPE ",0\r
+       DB      0FFh,0E4h,2Bh\r
+       DB      "CPO ",0\r
+       DB      0FFh,0FCh,83h\r
+       DB      "CM ",0\r
+       DB      0FFh,0F4h,8Bh\r
+       DB      "CP ",0\r
+       DB      0FFh,0C9h,05h\r
+       DB      "RET",0\r
+       DB      0FFh,0C8h,45h\r
+       DB      "RZ",0\r
+       DB      0FFh,0C0h,4Dh\r
+       DB      "RNZ",0\r
+       DB      0FFh,0D8h,15h\r
+       DB      "RC",0\r
+       DB      0FFh,0D0h,1Dh\r
+       DB      "RNC",0\r
+       DB      0FFh,0E8h,25h\r
+       DB      "RPE",0\r
+       DB      0FFh,0E0h,2Dh\r
+       DB      "RPO",0\r
+       DB      0FFh,0F8h,85h\r
+       DB      "RM",0\r
+       DB      0FFh,0F0h,8Dh\r
+       DB      "RP",0\r
+; Register based instructions\r
+       DB      0C0h,40h,01h\r
+       DB      "MOV d,s",0\r
+       DB      0C7h,06h,02h\r
+       DB      "MVI d,",0\r
+       DB      0F8h,90h,01h\r
+       DB      "SUB s",0\r
+       DB      0F8h,98h,01h\r
+       DB      "SBB s",0\r
+       DB      0F8h,80h,01h\r
+       DB      "ADD s",0\r
+       DB      0F8h,88h,01h\r
+       DB      "ADC s",0\r
+       DB      0F8h,0A0h,01h\r
+       DB      "ANA s",0\r
+       DB      0F8h,0B0h,01h\r
+       DB      "ORA s",0\r
+       DB      0F8h,0A8h,01h\r
+       DB      "XRA s",0\r
+       DB      0F8h,0B8h,01h\r
+       DB      "CMP s",0\r
+       DB      0C7h,04h,01h\r
+       DB      "INR d",0\r
+       DB      0C7h,05h,01h\r
+       DB      "DCR d",0\r
+; Register pair instructions\r
+       DB      0CFh,01h,03h\r
+       DB      "LXI p,",0\r
+       DB      0EFh,0Ah,01h\r
+       DB      "LDAX p",0\r
+       DB      0EFh,02h,01h\r
+       DB      "STAX p",0\r
+       DB      0CFh,03h,01h\r
+       DB      "INX p",0\r
+       DB      0CFh,0Bh,01h\r
+       DB      "DCX p",0\r
+       DB      0CFh,09h,01h\r
+       DB      "DAD p",0\r
+       DB      0CFh,0C5h,01h\r
+       DB      "PUSH p",0\r
+       DB      0CFh,0C1h,01h\r
+       DB      "POP p",0\r
+; Restart instruction\r
+       DB      0C7h,0C7h,01h\r
+       DB      "RST v",0\r
+; This entry always matches invalid opcodes\r
+       DB      00h,00h,01h\r
+       DB      "DB ",0\r
+; Misc Strings and messages\r
+ON:    DB      "ON ",0\r
+OFF:   DB      "OFF",0\r
+AUTMSG:        DB      "AUTOREG=",0\r
+SUBMSG:        DB      " SUBTRACE=",0\r
+TRCMSG:        DB      " TRACE=",0\r
+HTEXT: DB      "MON85 Commands:"\r
+       DB      0Dh,0Ah,0\r
+       DB      "A ON|OFF!Enable/Disable Automatic register display",0\r
+       DB      "B [bp address]!Set/Display breakpoints",0\r
+       DB      "C <src> <dest> <size>!Copy memory",0\r
+       DB      "D <address>!Display memory in assembly format",0\r
+       DB      "E <address>!Edit memory",0\r
+       DB      "F <start> <end> <value>!Fill memory",0\r
+       DB      "G [address]!Begin/Resume execution",0\r
+       DB      "H <start> <end>!Send out memory in Intel HEX format",0\r
+       DB      "I <port>!Input from port",0\r
+       DB      "L [address]!Load image into memory",0\r
+       DB      "M <address>!Display memory in hex dump format",0\r
+       DB      "O <port> <data>!Output to port",0\r
+       DB      "R [rp value]!Set/Display program registers",0\r
+       DB      "S ON|OFF!Enable/Disable Subroutine trace",0\r
+       DB      "T ON|OFF!Enable/Disable Trace mode",0\r
+       DB      "U [address]!Set/Display program base address",0\r
+       DB      0\r
+;\r
+; Read a character, and wait for it\r
+;\r
+INCHR: CALL    IN              ; Check for a character\r
+       ANA     A               ; Is there any data?\r
+       JZ      INCHR           ; Wait for it\r
+       RET\r
+;\r
+; Display HL in hexidecimal\r
+;\r
+HLOUT: MOV     A,H             ; Get HIGH byte\r
+       CALL    HPR             ; Output\r
+       MOV     A,L             ; Get LOW byte\r
+;\r
+; Display A in hexidecimal\r
+;\r
+HPR:   PUSH    PSW             ; Save low digit\r
+       RRC                     ; Shift\r
+       RRC                     ; high\r
+       RRC                     ; digit\r
+       RRC                     ; into low\r
+       CALL    HOUT            ; Display a single digit\r
+       POP     PSW             ; Restore low digit\r
+HOUT:  ANI     0Fh             ; Remove high digit\r
+       CPI     10              ; Convert to ASCII\r
+       SBI     2Fh\r
+       DAA\r
+       JMP     OUT             ; And output it\r
+;\r
+; Display message [PC]\r
+;\r
+PRTMSG:        POP     H               ; Get address\r
+       CALL    PRTSTR          ; Output message\r
+       PCHL                    ; And return\r
+;\r
+; Display message [HL]\r
+;\r
+PRTSTR:        MOV     A,M             ; Get byte from message\r
+       INX     H               ; Advance to next\r
+       ANA     A               ; End of message?\r
+       RZ                      ; Yes, exit\r
+       CALL    OUT             ; Output the character\r
+       JMP     PRTSTR          ; And proceed\r
+;\r
+; Handle output suspension\r
+;\r
+CHKSUS:        CALL    CRLF            ; New line\r
+       LDA     OFLAG           ; Is output suspended?\r
+       ANA     A               ; Test flag\r
+       JNZ     CHKS1           ; Yes it is\r
+       CALL    IN              ; Test for CONTROL-C interrupt\r
+       CPI     1Bh             ; ESCAPE?\r
+       JZ      REST            ; Abort\r
+       CPI     ' '             ; SPACE - Suspend command\r
+       RNZ\r
+       STA     OFLAG           ; Set the flag\r
+; Output is suspended, wait for command\r
+CHKS1: CALL    INCHR           ; Get char\r
+       CPI     ' '             ; One line?\r
+       RZ                      ; Allow it\r
+       CPI     1Bh             ; ESCAPE?\r
+       JZ      REST            ; Abort\r
+       CPI     0Dh             ; Resume?\r
+       JNZ     CHKS1           ; Keep going\r
+       SUB     A               ; Reset flag\r
+       STA     OFLAG           ; Write it\r
+       RET\r
+; Display a character if its printable\r
+OUTP:  CPI     ' '             ; < ' '\r
+       JC      OUTP1           ; Invalid, exchange it\r
+       CPI     7Fh             ; Printable?\r
+       JC      OUT             ; Ok to display\r
+OUTP1: MVI     A,'.'           ; Set to DOT to indicate invalid\r
+       JMP     OUT             ; And display\r
+;\r
+; Write a Line-Feed and Carriage-Return to console\r
+;\r
+CRLF:  MVI     A,0Dh           ; Carriage return\r
+       CALL    OUT             ; Output\r
+       MVI     A,0Ah           ; Line-feed\r
+;\r
+; User supplied I/O routines.\r
+;-----------------------------------------------------------\r
+; NOTE: "OUT" must appear first because "CRLF" falls into it.\r
+;\r
+; Write character in A to console (8251 uart)\r
+OUT:   PUSH    PSW             ; Save char\r
+OUT1:  IN      9               ; Get 8251 status\r
+       RRC                     ; Test TX bit\r
+       JNC     OUT1            ; Not ready\r
+       POP     PSW             ; Restore char\r
+       OUT     8               ; Write 8251 data\r
+       RET\r
+; Check for a character from the console (8251 uart)\r
+IN:    IN      9               ; Get 8251 status\r
+       ANI     00000010b       ; Test for ready\r
+       RZ                      ; No char\r
+       IN      8               ; Get 8251 data\r
+       RET\r
+;\r
+; Initialize the uart\r
+;\r
+; 8251A initialization, according to datasheet (3x 00h + RESET 040h)  \r
+INIT:  XRA     A               ; Insure not setup mode\r
+       OUT     9               ; Write once\r
+       OUT     9               ; Write again (now in operate mode)\r
+       OUT     9               ; Write again (now in operate mode)\r
+       MVI     A,01000000b     ; Reset\r
+       OUT     9               ; write it\r
+       MVI     A,01001110b     ; 8 data, 1 stop, x16\r
+       OUT     9               ; Write it\r
+       MVI     A,00110111b     ; RTS,DTR,Enable RX,TX\r
+       OUT     9               ; Write it\r
+       RET\r