-
Notifications
You must be signed in to change notification settings - Fork 14
Monitor User Guide
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.
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>
- 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 anA>
. - 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.
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
andloadhex
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
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.
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
.
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>