Skip to content

The Monitor

Underneath BASIC there's a second program in the ROM that lets you look at the machine's memory directly, byte by byte, and run code that isn't BASIC at all.

You don't need it. You can write games for years without opening it. But it's where you go when you want to know what's really happening, and it's the door into machine code.

Getting in

Three ways, all landing in the same place:

From BASIC, type BRK:

BRK
6502 MONITOR v1.1
BRK AT $E9D1
PC=E9D3 A=00 X=FF Y=68 SP=FA ---B-IZC
.

At startup, press Esc at the ENTER=BASIC ESC=MONITOR line instead of Enter.

From your own machine code, by executing a BRK instruction — which is how you use it as a debugger.

That single . is the Monitor's prompt, the way OK is BASIC's. The line above it is the state of the processor at the moment you arrived: where it was (PC), what was in its three registers (A, X, Y), and its flags. Don't worry about it yet.

X takes you back to BASIC, with your program intact:

X

OK

Looking at memory

M for memory, with an address in hexadecimal:

M 0800
.:0800 00 00 00 00 00 00 00 00 ........
.:0808 00 00 00 00 00 00 00 00 ........
.:0810 00 00 00 00 00 00 00 00 ........

Address on the left, eight bytes in hex, then the same bytes as characters on the right — which is how you spot text in among the numbers.

D disassembles instead, turning bytes back into 65C02 instructions:

D FF00
.,FF00  A9 1B     LDA #$1B
.,FF02  C9 08     CMP #$08
.,FF04  F0 18     BEQ $FF1E
A screen showing the Monitor banner, a BRK message, the register line, a dump of memory at 0800 that is all zeroes, and the register line again.
A whole visit: in with BRK, a look at $0800, and R to see the registers again.

Everything it does

CommandTypeWhat it does
XXExit to BASIC
RRDisplay saved CPU registers: `PC=xxxx A=xx X=xx Y=xx SP=xx NV-BDIZC`
MM [addr] [addr]Hex + ASCII memory dump (8 bytes/line); bare `M` continues from last address
DD [addr] [addr]Disassemble 65C02 instructions (20 lines default); supports the full WDC 65C02 + Rockwell instruction set
>> ADDR XX [XX XX ...]Deposit (write) bytes starting at address
FF ADDR1 ADDR2 XXFill memory range with a byte value
TT SRC_START SRC_END DESTTransfer (copy) a memory block; handles overlapping regions
HH ADDR1 ADDR2 XX [XX XX ...]Hunt (search) for a byte pattern in a range
CC ADDR1 ADDR2 ADDR3Compare two memory regions; prints differing addresses
GG [addr]Go — JMP to address (or saved PC); restores all registers via RTI
JJ [addr]JSR — call a subroutine; RTS returns to the monitor with register display
;; PC xxxx A xx X xx Y xx SP xx P xxModify saved registers (any subset, any order)
LL ["FILE"] [ADDR]Load from CompactFlash (with filename) or XModem (without) to address (default `$0800`). Loading at the default address lets `X` hand the program straight to BASIC, ready to `RUN`
SS ["FILE"] ADDR1 ADDR2Save to CompactFlash (with filename) or XModem (without)
@@List current disk's directory (prints `DISK n` header)
NN $XXXX or N +DDDDD or N %BBBBBBBBBBBBBBBBNumber conversion — hex (`$xx`), decimal (`+ddd`), or binary (`%bbbb`) input shown in all three bases
## NN (hex disk 00-FF selects); # alone reports the current diskSelect CF disk bank `NN` (hex 00–FF); `#` alone reports the current disk

The two you'll reach for besides M and D are R, which reprints that register line, and the two ways of running code:

  • J addr calls the code at that address like a subroutine. When it finishes, you land back at the . prompt with the registers on show. This is the one to use.
  • G addr jumps there and hands the machine over completely, interrupts and all. Nothing brings you back except a BRK in the code you jumped to — and because interrupts are off, the keyboard has stopped working, so if the code doesn't return you'll be reaching for the reset button.

Zeros disassemble as BRK

Point D at empty memory and you get page after page of BRK. Nothing is broken — the byte $00 is the BRK instruction, and unwritten memory is all zeros.

The easter egg

Type J FF00:

J FF00
\

That backslash is the prompt of Wozmon — Steve Wozniak's monitor for the Apple I, written in 1976, kept here byte for byte because it deserves to survive. It's 256 bytes long and it does three things:

  • FF00.FF0F — show a range of memory
  • 0300: A9 01 60 — put bytes into memory
  • 0300R — run from an address

It predates this machine by nearly fifty years and shares none of its commands. Press reset when you've had enough — your BASIC program will still be there.

Use J, not G

G FF00 prints the backslash and then ignores everything you type. Wozmon needs the keyboard, and G turns interrupts off on its way out — so the keystrokes never arrive. J leaves them on.

A screen showing the Monitor prompt, the command J FF00, a backslash on the next line, and a two-line hexadecimal dump of memory starting at FF00.
That backslash is Wozmon's prompt, and those sixteen bytes are Wozmon reading itself.

Written for BIOS v1.5. Released under the MIT License.