Skip to content

Monitor User Guide

J.B. Langston edited this page May 19, 2018 · 28 revisions

Monitor Commands

When the monitor starts up, it displays the version and then prompts for input with z80ctrl>.

z80ctrl 0.9 by J.B. Langston


type help to list available commands
z80ctrl>

We can type help to get a list of available commands. Each command is shown followed by a short description.

z80ctrl>help
available commands:
altmon  run altmon 8080 monitor
bus     display low-level bus status
break   set breakpoints
c       shorthand to continue debugging
cls     clear screen
dboot   boot disk using Altair disk bootloader
debug   debug code at address
dir     shows directory listing
disasm  disassembles memory location
dump    dump memory in hex and ascii
fill    fill memory with byte
help    list available commands
loadhex load intel hex file to memory
mount   mount a disk image
run     execute code at address
reset   reset the processor, with optional vector
savehex save intel hex file from memory
sboot   boot disk using SIMH bootloader
s       shorthand for step
step    step processor N cycles
unmount unmount a disk image
watch   set watch points
z80ctrl>

Any command that requires options will display its usage if you try to run it without any options.

z80ctrl>mount
usage: mount <drive #> <filename>

The dir command will list the files available on the SD card. Directories are indicated by a trailing /. We can list the files within a directory by passing the directory name to the dir command.

z80ctrl>dir
SYSTEM~1/     SCMON.HEX     HELLO.HEX     CPM2S.DSK     Z80OPS.HEX
CPM2D.DSK     SIMH/         DBL/
8 item(s)
z80ctrl>dir dbl
CPM1-24K.DSK  CPM1-48K.DSK  CPM2-48K.DSK  CPM2-56K.DSK  CPM2-63K.DSK
CPM2B24K.DSK  CPM2B63K.DSK  GAMES.DSK     KERMIT.DSK    SUPERC~1.DSK
SYSDEV.DSK    SYSGEN.DSK    WORDSTAR.DSK  ZORK.DSK      BASCOM.DSK
BASGAMES.DSK  BDSC.DSK
17 item(s)
z80ctrl>

Loading and Running Programs

z80ctrl supports loading and saving memory to and from Intel hex files. The load process prints out a message for each line in the hex file showing how many bytes were loaded and to what address. At the end of the process, the total number of bytes loaded is displayed.

z80ctrl>loadhex hello.hex
loading from hello.hex
loaded 0x10 bytes to 0x0100
loaded 0x10 bytes to 0x0110
loaded 0x0D bytes to 0x0120
loaded 0x002D bytes total

Once the program is loaded, it can be run.

z80ctrl>run 100
hello, world

This program has a halt instruction at the end, which stops the Z80 processor and returns control to the monitor.

Booting CP/M

z80ctrl is compatible with unmodified CP/M disk images from the SIMH project and the Altair Clone project. Disks are mounted by giving a drive number followed by the file to mount on that drive. z80ctrl supports up to 26 drives (0-25), which correspond to drive letters A-Z in CP/M. However, depending on the CP/M BIOS, it may not support more than several drives.

The disk image mounted in drive A: (0) can be booted from. There are two bootloaders: one for SIMH disk images (sboot), and one for DBL disk images used by the Altair Clone project (dboot). Disk images must be booted using the appropriate bootloader.

We will mount a CP/M 2.2 disk image from the SIMH project on A: and a secondary disk with some games on drive B:, then boot CP/M.

z80ctrl>mount 0 simh/cpm2.dsk
z80ctrl>mount 1 simh/games.dsk
z80ctrl>sboot

64K CP/M Version 2.2 (SIMH ALTAIR 8800, BIOS V1.27, 2 HD, 02-May-2009)

A>

We can list the files on the drive, and run one of the programs:

A>dir
A: ASM      COM : BDOS     MAC : SYSCPM2  SUB : BOOT     MAC
A: SYSCPM2Z SUB : CBIOSX   MAC : CCP      MAC : CCPZ     MAC
A: CCPZ     TXT : CFGCCP   LIB : CFGCCPZ  LIB : COPY     COM
A: CPU      COM : CPU      MAC : CREF80   COM : DDT      COM
A: DDTZ     COM : MOVER    MAC : DO       COM : DSKBOOT  MAC
A: DUMP     COM : ED       COM : ELIZA    BAS : EX       MAC
A: EX       SUB : EX8080   COM : EXZ80ALL COM : EXZ80DOC COM
A: FORMAT   COM : GO       COM : HALT     COM : PRELIM   MAC
A: HDSKBOOT MAC : L80      COM : LADDER   COM : LADDER   DAT
A: LIB80    COM : LOAD     COM : LS       COM : LU       COM
A: M80      COM : MBASIC   COM : MC       SUB : MCC      SUB
A: MCCL     SUB : OTHELLO  COM : PIP      COM : EC8080   LIB
A: PRELIM   COM : ECZ80ALL LIB : RSETSIMH COM : RSETSIMH MAC
A: ECZ80DOC LIB : SID      COM : BOOT     COM : STAT     COM
A: SUBMIT   COM : SURVEY   COM : SURVEY   MAC : SPEED    COM
A: SYSCOPY  COM : URL      COM : TIMER    COM : TIMER    MAC
A: UNCR     COM : UNERA    COM : UNERA    MAC : USQ      COM
A: W        COM : WM       COM : WM       HLP : WORM     COM
A: XSUB     COM : ZAP      COM : ZSID     COM : ZTRAN4   COM
A: BOOTGEN  COM : DIF      COM : HDIR     COM : R        COM
A: SHOWSEC  COM : XFORMAT  COM

A>survey
                *** System Survey (June 82) ***

Drive A: 746K bytes in 103 files with 246K bytes remaining

Memory map:
0       8       16      24      32      40      48      56      64
|       |       |       |       |       |       |       |       |
 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTCCCBBBB
T=TPA   C=CPM   B=BIOS or unassigned    R=ROM or bad
BIOS at F203    iobyte E5       drive 00        BDOS at E406

65535 Bytes RAM         0 Bytes ROM             58374 Bytes in TPA
0 Bytes Empty           65535 Total Active Bytes

Active I/O ports:
08 09 0A
10 11
5 Ports active

A>

Now we can switch to the B: drive and look at the files on the second disk we mounted.

B>dir
B: ADVT     DAT : ADVDDIA  SAV : ADVDDOM  SAV : ADVI     DAT
B: ADVI     PTR : ADVT     PTR : ADV      COM : CATCHUM  COM
B: CREDITS      : QT       ASM : QTERMR   PAT : QTERMW   PAT
B: README   1ST : CATCHUM  DAT : ROGUE    COM : WORTE    TXT
B: ROGUE    DOC : ROGUE    NOT : SCREEN   001 : SCREEN   002
B: SCREEN   003 : SCREEN   004 : SCREEN   005 : SCREEN   006
B: SCREEN   007 : SCREEN   008 : SCREEN   009 : SCREEN   010
B: SCREEN   011 : SCREEN   012 : SCREEN   013 : SCREEN   014
B: SCREEN   015 : SCREEN   016 : SCREEN   017 : SCREEN   018
B: SCREEN   019 : SCREEN   020 : SCREEN   021 : SCREEN   022
B: SCREEN   023 : SCREEN   024 : SCREEN   025 : SCREEN   026
B: SCREEN   027 : SCREEN   028 : SCREEN   029 : SCREEN   030
B: SCREEN   031 : SCREEN   032 : SCREEN   033 : SCREEN   034
B: SCREEN   035 : SCREEN   036 : SCREEN   037 : SCREEN   038
B: SCREEN   039 : SCREEN   040 : SCREEN   041 : SCREEN   042
B: SCREEN   043 : SCREEN   044 : SCREEN   045 : SCREEN   046
B: SCREEN   047 : SCREEN   048 : SCREEN   049 : SCREEN   050
B: WANDERER COM : WANDERER DOC : LADDER   COM : LADDER   DAT
B: WORM     COM

If we attempt to access a drive that has not been mounted, we will get a Bad Sector error:

B>c:
Bdos Err On C: Bad Sector

We can halt CP/M using the halt button on the z80ctrl board. The z80ctrl> prompt is displayed again. Now, we will mount and run some disks using the Altair Disk Boot Loader format.

z80ctrl>mount 0 dbl/cpm2b63k.dsk
z80ctrl>mount 1 dbl/zork.dsk
z80ctrl>dboot


63K CP/M 2.2b v2.0
For Altair 8" Floppy

A>dir
A: L80      COM : LADDER   COM : ED       COM : ASM      COM
A: DUMP     COM : XSUB     COM : PCGET    COM : LS       COM
A: SUBMIT   COM : LOAD     COM : SURVEY   COM : VIEW     COM
A: LADDER   DAT : LUNAR    BAS : M80      COM : MAC      COM
A: MBASIC   COM : PIP      COM : STAT     COM : DDT      COM
A: IOBYTE   TXT : NSWP     COM : SYSGEN   COM : AFORMAT  COM
A: MOVCPM8  COM : OTHELLO  COM : STARTRK  BAS : TICTAK   BAS
A: WM       COM : WM       HLP : CRC      COM : PCPUT    COM
A: ACOPY    COM : STARINS  BAS : DOWNLOAD COM
A>b:
B>dir
B: ZORK1    COM : ZORK1    DAT : ZORK2    DAT : ZORK3    DAT
B: ZORK2    COM : ZORK3    COM
B>zork1
ZORK I: The Great Underground Empire
Copyright (c) 1981, 1982, 1983 Infocom, Inc. All rights
reserved.
ZORK is a registered trademark of Infocom, Inc.
Revision 88 / Serial number 840726

West of House
You are standing in an open field west of a white house, with
a boarded front door.
There is a small mailbox here.

>

If we try to boot a disk image with the wrong boot loader, it will hang. We can get back to the z80ctrl> prompt by pressing the halt button on the board.

z80ctrl>mount 0 dbl/cpm2b63k.dsk
z80ctrl>sboot

Example Debugging Session

Sometimes before a debugging session, it's helpful to clear out memory. We can do this with the fill command, and then use dump to confirm that it was cleared.

z80ctrl>fill 0 ffff 0
z80ctrl>dump 100
0100 01ff
0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................

Now we can reload the hello world program and show another hex dump of the program starting at address 100 and see the bytes that were loaded in. ASCII is shown to the right. You can see the "hello, world" string that the program displays. Dots are used for non-printable characters.

z80ctrl>dump 100
0100 01ff
0100: 31 FF FF 21 1E 01 CD 0A 01 76 7E A7 C8 CD 13 01   1..!.....v~.....
0110: 23 18 F7 F5 DB 10 CB 4F 28 FA F1 D3 11 C9 68 65   #......O(.....he
0120: 6C 6C 6F 2C 20 77 6F 72 6C 64 0D 0A 00 00 00 00   llo, world......
0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
01F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................

Now we can disassemble the program from memory. The disassembler output shows the hex address (4 digits), followed by the hex bytes of the instruction (2 digits per byte), then the ASCII representation of those bytes. Again dots are used for non-printable characters. Starting at address 011e, the program ends and the string data begins. The disassembler has now way of knowing this is not code, but the ASCII output helps you recognize that it's a string.

z80ctrl>disasm 100 130
0100  31 ff ff         1..    LD SP,FFFFH
0103  21 1e 01         !..    LD HL,011EH
0106  cd 0a 01         ...    CALL 010AH
0109  76               v      HALT
010a  7e               ~      LD A,(HL)
010b  a7               .      AND A
010c  c8               .      RET Z
010d  cd 13 01         ...    CALL 0113H
0110  23               #      INC HL
0111  18 f7            ..     JR -9
0113  f5               .      PUSH AF
0114  db 10            ..     IN A,(10H)
0116  cb 4f            .O     BIT 1,A
0118  28 fa            (.     JR Z,-6
011a  f1               .      POP AF
011b  d3 11            ..     OUT (11H),A
011d  c9               .      RET
011e  68               h      LD L,B
011f  65               e      LD H,L
0120  6c               l      LD L,H
0121  6c               l      LD L,H
0122  6f               o      LD L,A
0123  2c               ,      INC L
0124  20 77             w     JR NZ,119
0126  6f               o      LD L,A
0127  72               r      LD (HL),D
0128  6c               l      LD L,H
0129  64               d      LD H,H
012a  0d               .      DEC C
012b  0a               .      LD A,(BC)
012c  00               .      NOP
012d  00               .      NOP
012e  00               .      NOP
012f  00               .      NOP
0130  00               .      NOP

Now we enable watches on bus activity and opcode fetches and then display the watch status. If no address is specified, the entire address range is used.

z80ctrl>watch bus
z80ctrl>watch opfetch
z80ctrl>watch
watch status:
        bus: 0000-ffff
        memrd: disabled
        memwr: disabled
        iord: disabled
        iowr: disabled
        opfetch: 0000-ffff

usage:
        watch <type> [start] [end]
        watch <type> off to disable type
        watch off to disable all

We also enable breaks on IO writes and display the status to confirm:

z80ctrl>break iowr
z80ctrl>break
break status:
        memrd: disabled
        memwr: disabled
        iord: disabled
        iowr: 0000-00ff
        opfetch: disabled

usage:
        break <type> [start] [end]
        break <type> off to disable type
        break off to disable all

Now we will debug the program starting at address 100. The bus watch we enabled shows the bus status for every T cycle. The values of the address and data bus are shown, then the status of the control lines: rd/wr/rfsh (read, write refresh) mem/io (memory or IO request), m1 (start of a machine cycle), and so on.

Because we also enabled watches on opfetch, each instruction is disassembled in real time as it is executed by the Z80. The mnemonic and operands are displayed after the full instruction and its operands have been fetched. In front of the mnemonic, the starting address of the instruction is displayed.

z80ctrl>debug 100
        ff17 00      rd   mem
        ff17 01
        0000 01                  m1
        0000 c3      rd   mem    m1
        0000 c3      rfsh
        0000 c3      rfsh mem
        0001 c3
        0001 00      rd   mem
        0001 00      rd   mem
        0002 01
        0002 01      rd   mem
        0002 01      rd   mem
        0100 01                  m1
        0000    JP 0100H
        0100 31 1    rd   mem    m1
        0001 31 1    rfsh
        0001 31 1    rfsh mem
        0101 31 1
        0101 ff      rd   mem
        0101 ff      rd   mem
        0102 ff
        0102 ff      rd   mem
        0102 ff      rd   mem
        0103 ff                  m1
        0100    LD SP,FFFFH
        0103 21 !    rd   mem    m1
        0002 21 !    rfsh
        0002 21 !    rfsh mem
        0104 21 !
        0104 1e      rd   mem
        0104 1e      rd   mem
        0105 1f
        0105 01      rd   mem
        0105 01      rd   mem
        0106 01                  m1
        0103    LD HL,011EH
        0106 cd      rd   mem    m1
        0003 cd      rfsh
        0003 cd      rfsh mem
        0107 cd
        0107 0a      rd   mem
        0107 0a      rd   mem
        0108 0b
        0108 01      rd   mem
        0108 01      rd   mem
        0108 01
        0106    CALL 010AH
        fffe 01
        fffe 01           mem
        fffe 01      wr   mem
        fffd 01
        fffd 09           mem
        fffd 09      wr   mem
        010a 09                  m1
        010a 7e ~    rd   mem    m1
        0004 7f      rfsh
        010a    LD A,(HL)
        0004 7f      rfsh mem
        011e 7f
        011e 68 h    rd   mem
        011e 68 h    rd   mem
        010b 69 i                m1
        010b a7      rd   mem    m1
        0005 a7      rfsh
        010b    AND A
        0005 a7      rfsh mem
        010c a7                  m1
        010c c8      rd   mem    m1
        0006 c9      rfsh
        010c    RET Z
        0006 c9      rfsh mem
        0006 c9
        010d c9                  m1
        010d cd      rd   mem    m1
        0007 cd      rfsh
        0007 cd      rfsh mem
        010e cd
        010e 13      rd   mem
        010e 13      rd   mem
        010f 13
        010f 01      rd   mem
        010f 01      rd   mem
        010f 01
        010d    CALL 0113H
        fffc 01
        fffc 01           mem
        fffc 01      wr   mem
        fffb 01
        fffb 10           mem
        fffb 10      wr   mem
        0113 11                  m1
        0113 f5      rd   mem    m1
        0008 f5      rfsh
        0113    PUSH AF
        0008 f5      rfsh mem
        0008 f5
        fffa f5
        fffa 68 h         mem
        fffa 68 h    wr   mem
        fff9 69 i
        fff9 38 8         mem
        fff9 38 8    wr   mem
        0114 39 9                m1
        0114 db      rd   mem    m1
        0009 db      rfsh
        0009 db      rfsh mem
        0115 db
        0115 10      rd   mem
        0115 10      rd   mem
        6810 11
        0114    IN A,(10H)
        6810 02
        0116 02                  m1
        0116 cb      rd   mem    m1
        000a cb      rfsh
        000a cb      rfsh mem
        0117 cb                  m1
        0117 4f O    rd   mem    m1
        000b 4f O    rfsh
        0116    BIT 1,A
        000b 4f O    rfsh mem
        0118 4f O                m1
        0118 28 (    rd   mem    m1
        000c 2a *    rfsh
        000c 2a *    rfsh mem
        0119 2a *
        0119 fa      rd   mem
        0119 fa      rd   mem
        011a fa                  m1
        0118    JR Z,-6
        011a f1      rd   mem    m1
        000d f3      rfsh
        011a    POP AF
        000d f3      rfsh mem
        fff9 f3
        fff9 38 8    rd   mem
        fff9 38 8    rd   mem
        fffa 3a :
        fffa 68 h    rd   mem
        fffa 68 h    rd   mem
        011b 6a j                m1
        011b d3      rd   mem    m1
        000e d3      rfsh
        000e d3      rfsh mem
        011c d3
        011c 11      rd   mem
        011c 11      rd   mem
        6811 13
        011b    OUT (11H),A
h       6811 68 h

Once the first IO write is encountered (outputting the h in hello, world), the breakpoint activates and execution stops. Now we can single step instructions:

z80ctrl>s
        ff2d 00                                            busack
        fffb 00
        fffb 10      rd   mem
        fffb 10      rd   mem
        fffc 10
        fffc 01      rd   mem
        fffc 01      rd   mem
        0110 01                  m1
        0110 23 #    rd   mem    m1
        0010 23 #    rfsh
        0110    INC HL

You can see that only enough bus cycles were run to execute a single instruction. We can continue stepping through a few more instructions, one at a time.

z80ctrl>s
        0010 00      rfsh mem
        0010 00
        0010 00
        0111 00                  m1
        0111 18      rd   mem    m1
        0011 18      rfsh
        0011 18      rfsh mem
        0112 18
        0112 f7      rd   mem
        0112 f7      rd   mem
        0112 f7
        0111    JR -9
z80ctrl>s
        0112 00
        0112 00
        0112 00
        0112 00
        010a 00                  m1
        010a 7e ~    rd   mem    m1
        0012 7e ~    rfsh
        010a    LD A,(HL)
z80ctrl>s
        0012 00      rfsh mem
        011f 00
        011f 65 e    rd   mem
        011f 65 e    rd   mem
        010b 65 e                m1
        010b a7      rd   mem    m1
        0013 a7      rfsh
        010b    AND A

We can now continue, and the program will run until the next breakpoint is encountered.

z80ctrl>c
        0013 00      rfsh mem
        010c 00                  m1
        010c c8      rd   mem    m1
        0014 c8      rfsh
        010c    RET Z
        0014 c8      rfsh mem
        0014 c8
        010d c8                  m1
        010d cd      rd   mem    m1
        0015 cd      rfsh
        0015 cd      rfsh mem
        010e cd
        010e 13      rd   mem
        010e 13      rd   mem
        010f 13
        010f 01      rd   mem
        010f 01      rd   mem
        010f 01
        010d    CALL 0113H
        fffc 01
        fffc 01           mem
        fffc 01      wr   mem
        fffb 01
        fffb 10           mem
        fffb 10      wr   mem
        0113 10                  m1
        0113 f5      rd   mem    m1
        0016 f5      rfsh
        0113    PUSH AF
        0016 f5      rfsh mem
        0016 f5
        fffa f5
        fffa 65 e         mem
        fffa 65 e    wr   mem
        fff9 65 e
        fff9 34 4         mem
        fff9 34 4    wr   mem
        0114 34 4                m1
        0114 db      rd   mem    m1
        0017 db      rfsh
        0017 db      rfsh mem
        0115 db
        0115 10      rd   mem
        0115 10      rd   mem
        6510 10
        0114    IN A,(10H)
        6510 02
        0116 02                  m1
        0116 cb      rd   mem    m1
        0018 cb      rfsh
        0018 cb      rfsh mem
        0117 cb                  m1
        0117 4f O    rd   mem    m1
        0019 4f O    rfsh
        0116    BIT 1,A
        0019 4f O    rfsh mem
        0118 4f O                m1
        0118 28 (    rd   mem    m1
        001a 2a *    rfsh
        001a 2a *    rfsh mem
        0119 2a *
        0119 fa      rd   mem
        0119 fa      rd   mem
        011a fa                  m1
        0118    JR Z,-6
        011a f1      rd   mem    m1
        001b f3      rfsh
        011a    POP AF
        001b f3      rfsh mem
        fff9 f3
        fff9 34 4    rd   mem
        fff9 34 4    rd   mem
        fffa 36 6
        fffa 65 e    rd   mem
        fffa 65 e    rd   mem
        011b 67 g                m1
        011b d3      rd   mem    m1
        001c d3      rfsh
        001c d3      rfsh mem
        011c d3
        011c 11      rd   mem
        011c 11      rd   mem
        6511 13
        011b    OUT (11H),A
e       6511 65 e

Once again it stops at an IO write (the e in hello world). We'll single step through a few more instructions, then continue.

z80ctrl>s
        ff2d 00                                            busack
        fffb 00
        fffb 10      rd   mem
        fffb 10      rd   mem
        fffc 10
        fffc 01      rd   mem
        fffc 01      rd   mem
        0110 01                  m1
        0110 23 #    rd   mem    m1
        0010 23 #    rfsh
        0110    INC HL
z80ctrl>s
        0010 00      rfsh mem
        0010 00
        0010 00
        0111 00                  m1
        0111 18      rd   mem    m1
        0011 18      rfsh
        0011 18      rfsh mem
        0112 18
        0112 f7      rd   mem
        0112 f7      rd   mem
        0112 f7
        0111    JR -9
z80ctrl>s
        0112 00
        0112 00
        0112 00
        0112 00
        010a 00                  m1
        010a 7e ~    rd   mem    m1
        0012 7e ~    rfsh
        010a    LD A,(HL)
z80ctrl>s
        0012 00      rfsh mem
        011f 00
        011f 65 e    rd   mem
        011f 65 e    rd   mem
        010b 65 e                m1
        010b a7      rd   mem    m1
        0013 a7      rfsh
        010b    AND A
z80ctrl>c
        0013 00      rfsh mem
        010c 00                  m1
        010c c8      rd   mem    m1
        0014 c8      rfsh
        010c    RET Z
        0014 c8      rfsh mem
        0014 c8
        010d c8                  m1
        010d cd      rd   mem    m1
        0015 cd      rfsh
        0015 cd      rfsh mem
        010e cd
        010e 13      rd   mem
        010e 13      rd   mem
        010f 13
        010f 01      rd   mem
        010f 01      rd   mem
        010f 01
        010d    CALL 0113H
        fffc 01
        fffc 01           mem
        fffc 01      wr   mem
        fffb 01
        fffb 10           mem
        fffb 10      wr   mem
        0113 10                  m1
        0113 f5      rd   mem    m1
        0016 f5      rfsh
        0113    PUSH AF
        0016 f5      rfsh mem
        0016 f5
        fffa f5
        fffa 65 e         mem
        fffa 65 e    wr   mem
        fff9 65 e
        fff9 34 4         mem
        fff9 34 4    wr   mem
        0114 34 4                m1
        0114 db      rd   mem    m1
        0017 db      rfsh
        0017 db      rfsh mem
        0115 db
        0115 10      rd   mem
        0115 10      rd   mem
        6510 10
        0114    IN A,(10H)
        6510 02
        0116 02                  m1
        0116 cb      rd   mem    m1
        0018 cb      rfsh
        0018 cb      rfsh mem
        0117 cb                  m1
        0117 4f O    rd   mem    m1
        0019 4f O    rfsh
        0116    BIT 1,A
        0019 4f O    rfsh mem
        0118 4f O                m1
        0118 28 (    rd   mem    m1
        001a 2a *    rfsh
        001a 2a *    rfsh mem
        0119 2a *
        0119 fa      rd   mem
        0119 fa      rd   mem
        011a fa                  m1
        0118    JR Z,-6
        011a f1      rd   mem    m1
        001b f3      rfsh
        011a    POP AF
        001b f3      rfsh mem
        fff9 f3
        fff9 34 4    rd   mem
        fff9 34 4    rd   mem
        fffa 36 6
        fffa 65 e    rd   mem
        fffa 65 e    rd   mem
        011b 67 g                m1
        011b d3      rd   mem    m1
        001c d3      rfsh
        001c d3      rfsh mem
        011c d3
        011c 11      rd   mem
        011c 11      rd   mem
        6511 13
        011b    OUT (11H),A
e       6511 65 e

Now we'll disable bus watching, but instruction execution is still being watched. Now if we single-step, it only outputsthe instruction and the address it started with. The bus cycles used to fetch the instruction are not shown.

z80ctrl>watch bus off
z80ctrl>s
        011d    RET
z80ctrl>s
        0110    INC HL
z80ctrl>s
        0111    JR -9
z80ctrl>s
        010a    LD A,(HL)
z80ctrl>s
        010b    AND A
z80ctrl>s
        010c    RET Z

Continuing, we can see all the instructions that execute for a single iteration of the loop that outputs each character.

z80ctrl>c
        010d    CALL 0113H
        0113    PUSH AF
        0114    IN A,(10H)
        0116    BIT 1,A
        0118    JR Z,-6
        011a    POP AF
        011b    OUT (11H),A
lz80ctrl>c
        011d    RET
        0110    INC HL
        0111    JR -9
        010a    LD A,(HL)
        010b    AND A
        010c    RET Z
        010d    CALL 0113H
        0113    PUSH AF
        0114    IN A,(10H)
        0116    BIT 1,A
        0118    JR Z,-6
        011a    POP AF
        011b    OUT (11H),A

We stopped again on an IO write, which is outputting the second l in hello world. When we're finished debugging, we can run the program, and it will continue running at full speed from the location where execution was stopped. Breakpoints and watches are ignored while running at full speed. The program finishes printing out "o, world". Once the program finishes, it executes a HALT instruction, which stops the Z80 and automatically returns control to the monitor.

lz80ctrl>run
o, world
z80ctrl>

I have also made YouTube video demonstrating the monitor software.

Clone this wiki locally