Skip to content

Monitor User Guide

J.B. Langston edited this page Jul 19, 2020 · 28 revisions

This is a quick tutorial to introduce the most important z80ctrl features. Not every command is covered. I have also made a more in depth YouTube video demonstrating the monitor software.

Monitor Basics

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

      ___   ___       _        _
  ___( _ ) / _ \  ___| |_ _ __| |
 |_  / _ \| | | |/ __| __| '__| |
  / / (_) | |_| | (__| |_| |  | |
 /___\___/ \___/ \___|\__|_|  |_|
 by J.B. Langston (d03d632)

type help to list available commands
z80ctrl:/>

The hex number in parentheses is the git commit hash of the build installed on your z80ctrl board. If you report a problem, it helps me to know what version you're using.

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

z80ctrl:/>help
available commands:
assign  assign a device to a port
attach  attach virtual uart
base    set the base memory address
baud    configure UART baud rate
boot    boot from specified disk image
bus     display low-level bus status
break   set breakpoints
cd      change directory
clkdiv  set Z80 clock divider
cls     clear screen
copy    copy a file (alias cp)
date    display or set the date on the rtc
debug   debug code at address (alias c)
del     erase a file (alias era, rm)
dir     shows directory listing in long format
disasm  disassembles memory location
do      execute a batch file
dump    dump memory in hex and ascii (alias d)
fill    fill memory with byte
halt    enable or disable halt
haltkey enable halt via keyboard shortcut
help    list available commands
in      read a value from a port
loadbin load binary file to memory
loadhex load intel hex file to memory
ls      shows directory listing in wide format
mkdir   create a subdirectory (alias md)
mount   mount a disk image
out     write a value to a port
poke    poke values into memory
ren     rename/move a file or directory (alias mv)
run     execute code at address
savebin save binary file from memory
savehex save intel hex file from memory
screen  set screen size
step    step processor N cycles (alias s)
tmsreg  report tms registers
tmsdump dump tms memory in hex and ascii
tmsfill fill tms memory with byte
tmslbin load binary file to tms memory
unmount unmount a disk image
watch   set watch points
xmrx    receive a file via xmodem
xmtx    send a file via xmodem
z80ctrl:/>

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

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

Compatible Software

  • z80ctrl is compatible with disk images from Peter Schorn's AltairZ80 emulator. To start with, I recommend downloading CP/M 2.2 from Peter Schorn's website. Copy cpm2.dsk to your SD card and run boot cpm2.dsk to boot it. You should get an A>.
  • CP/M 2.2 disk images from the Altair Clone project will also work, but there's not much there that isn't already available from AltairZ80.
  • The Humongous CP/M Archive has a massive collection of CP/M software including public domain software from the Walnut Creek CP/M CD-ROM.
  • Commercial CP/M software is available on the Retrocomputing Archive.

Running Programs

z80ctrl provides multiple ways to load and run programs.

  • Run a CP/M .COM program by typing its name (with or without the extension)
  • Run a z80ctrl .PRG program by typing its name (with or without the extension)
  • Explicitly load a binary or hex file using the loadbin and loadhex commands
  • Explicitly run code at a specified address using the run comamnd

Important: To run CP/M programs, z80ctrl requires a BDOS stub file called bdos.bin in the root directory. This can also be assembled from bdos.asm file using sjasm.

.COM programs can be run just by typing their name. The extension is optional. If the program's name conflicts with a built-in z80ctrl command, the .COM extension can be included to force z80ctrl to run the program instead of running the built-in command. z80ctrl's BDOS emulation allows CP/M programs to access files directly from the FAT32 filesystem on the SD card without requiring a disk image. The program can access any file in the current directory via the A: drive.

z80ctrl:/BASIC>dir
BASCOM.COM   BASCOM.HLP   BASCOM.SUB   BASCOM2.HLP  BASLIB.REL   BCLOAD
BLACKJAK.BAS BLACKJAK.COM BLACKJAK.INT BRUN.COM     CB80.COM     CB80.IRL
CB80.OV1     CB80.OV2     CB80.OV3     CB80.SUB     CBASE2.COM   CBASIC.COM
CBASIC.SUB   CBASXREF.COM CHASE.BAS    CRUN.COM     CRUN2.COM    DEMOGRAF.BAS
ELIZA.BAS    GRAPHCOM.BAS GRAPHR.BAS   GSXPREP.BAS  HAMURS.BAS   HORSE.BAS
KING4K.BAS   LANDER4K.BAS LIB.COM      LINK.COM     LK80.COM     MBASIC.COM
MBASIC45.COM MBASIC51.COM MBASIC52.COM MSTMND.BAS   OBSLIB.REL   RANTEST.ASC
RANTEST.BAS  RANTEST.COM  READ.ME      ROCKET.BAS   SAMPLE.BAS   SAMPLE.SUB
SIEVE.BAS    STARTREK.BAS TAXMAN.BAS   TRADE.BAS    TSTCIR.BAS   WUMPUS4K.BAS
XBASIC.COM   LIFE.BAS     DESCEND.BAS  MANDEL.BAS   RTC.BAS
59 item(s)
z80ctrl:/BASIC>mbasic chase
BASIC-80 Rev. 5.21
[CP/M Version]
Copyright 1977-1981 (C) by Microsoft
Created: 28-Jul-81
37944 Bytes free






THIS IS THE GAME OF CHASE
YOU ARE IN A HIGH VOLTAGE MAZE WITH FIVE
SECURITY MACHINES (+) TRYING TO DESTROY YOU (X).
YOU MUST MANEUVER THE SECURITY MACHINES INTO
THE HIGH VOLTAGE FENCE POSTS (O), OR INTO EACH OTHER
IN ORDER TO SURVIVE.   GOOD LUCK.

MOVES ARE:    1 2 3
              8 * 4     0  IS NO MOVE
              7 6 5     9  GIVE UP

 .  .  .  .  .  .  .  .  .  .

OOOOOOOOOOOOOOOOOOOO
O              +   O
O    O+    O    O  O       5 SECURITY MACHINES LEFT
OO   O    +    O   O
O      +           O
O        O     O   O
OX                 O            1 2 3
OO        OO       O            8 * 4     0  IS NO MOVE
OO          O O O+ O            7 6 5     9  GIVE UP
OOOOOOOOOOOOOOOOOOOO
MOVE? ^C
Break in 630
Ok
system

z80ctrl:/BASIC>

The emulation is not perfect yet and there are a few programs, such as ZDE, which don't work properly, but most programs do.

z80ctrl will also automatically load and run files with a .PRG extension. The first two bytes of the .PRG file must contain the address at which the program will be loaded and executed. Otherwise, it is just a raw binary file. This idea is stolen from the Commodore 64 files with the same extension.

BDOS runtime support is not provided for .PRG files but they can access any hardware or services provided by z80ctrl directly via the I/O ports. An example .PRG program filecopy.asm is provided, which uses the filedma.asm library to access the FatFS DMA interface provided by z80ctrl. Using the native FatFS interface is faster than BDOS emulation and can access files in multiple directories.

Finally, Intel Hex files and binary files can be manually loaded and executed.

z80ctrl>loadhex hello.hex
loading from hello.hex
loaded 45 bytes total from 0100-012c

Once the program is loaded, it can be run.

z80ctrl>run 100
hello, world

CP/M Disk Images

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 SIMH BIOS only supports A-H for traditional floppies and uses DMA transfers for drives I-P. Currently, DMA support is experimental, so use drives A-H for reliable operation.

The disk image mounted in drive A: (0) can be booted from using the boot command. You can optionally pass a filename to the boot command as a short cut to automatically mount the disk image on drive 0 and boot it.

Note that different CP/M BIOSes may not be compatible with each other. Disk images formatted using one version of CP/M may not be readable with a different BIOS, so be sure you boot from a disk that supports the format of any other mounted disk images.

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>boot

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.

File Management

z80ctrl provides the standard DOS-like commands for managing files. All of them work like you would expect. The z80ctrl prompt shows the currently active directory.

The dir command lists the files in the current directory. Directories are indicated by a trailing /.

z80ctrl:/>dir
MSX/         TMS/         DISKS/       VGM/         HITECH/      BBCBASIC/
ZDE/         MUSIC/       HELLO.PRG    CPM/         VDE/         MISC/
CPM2SRC/     GAMES/       Z80ASM/      BDOS.BIN     WS33/        BASIC/
SIMHFILE/    WALNUT/      ROMWBW/      CV/          TP3/         SCM.HEX
SCM.BIN
25 item(s)

The md command will make a new directory.

z80ctrl:/>md test
z80ctrl:/>dir
MSX/         TEST/        TMS/         DISKS/       VGM/         HITECH/
BBCBASIC/    ZDE/         MUSIC/       HELLO.PRG    CPM/         VDE/
MISC/        CPM2SRC/     GAMES/       Z80ASM/      BDOS.BIN     WS33/
BASIC/       SIMHFILE/    WALNUT/      ROMWBW/      CV/          TP3/
SCM.HEX      SCM.BIN
26 item(s)

The cd command changes to the new directory. Note that it is now displayed in the prompt. Running dir shows that there are no files in the directory as expected.

z80ctrl:/>cd test
z80ctrl:/TEST>dir

file not found

We use the copy command to copy a file from the root directory, and now it shows up in the dir output of the new directory.

z80ctrl:/TEST>cd ..
z80ctrl:/>copy hello.prg test
z80ctrl:/>cd test
z80ctrl:/TEST>dir
HELLO.PRG
1 item(s)
z80ctrl:/TEST>copy hello.prg hello2.prg
z80ctrl:/TEST>dir
HELLO.PRG    HELLO2.PRG
2 item(s)

The ren command changes a file's name.

z80ctrl:/TEST>ren hello2.prg hello3.prg
z80ctrl:/TEST>dir
HELLO.PRG    HELLO3.PRG
2 item(s)

The del command removes a file.

z80ctrl:/TEST>del hello3.prg
z80ctrl:/TEST>dir
HELLO.PRG
1 item(s)
z80ctrl:/TEST>del hello.prg
z80ctrl:/TEST>dir

file not found
z80ctrl:/TEST>cd ..

The rd command will remove an empty directory.

z80ctrl:/>rd test
z80ctrl:/>dir
MSX/         TMS/         DISKS/       VGM/         HITECH/      BBCBASIC/
ZDE/         MUSIC/       HELLO.PRG    CPM/         VDE/         MISC/
CPM2SRC/     GAMES/       Z80ASM/      BDOS.BIN     WS33/        BASIC/
SIMHFILE/    WALNUT/      ROMWBW/      CV/          TP3/         SCM.HEX
SCM.BIN
25 item(s)
z80ctrl:/>

In most cases aliases are provided for the DOS, Linux, and CP/M name of the command, and any version will work the same. For example, del also recognizes rm and era.

Debugging

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. The "hello, world" string that the program displays is visible. Dots are used for non-printable characters.

z80ctrl>loadhex hello.hex
loading from hello.hex
loaded 45 bytes total from 0100-012c
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 doesn't know this is not code, but the ASCII output helps identify strings.

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

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

The debugger stopped again on an IO write, which is outputting the second l in hello world. When finished debugging, just 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>