Apple II System Monitor
Apple II System Monitor Commands
Quick Navigation
Entering the Monitor
| Method | Command | Description |
|---|---|---|
| From BASIC | CALL -151 | Enter monitor from Applesoft or Integer BASIC |
| From DOS | CALL -151 | Same as BASIC |
| Reset + Key | RESET then CTRL+B | On older Apple IIs |
| From Assembly | JMP $FF69 | Jump to monitor entry point |
| Break | BRK | Execute BRK instruction (if vector set) |
| Power On | * | Some Apple II models boot to monitor |
The monitor prompt is an asterisk (*)
Basic Commands
| Command | Syntax | Description | Example |
|---|---|---|---|
| Exit Monitor | CTRL+C or CTRL+B | Return to BASIC | ^C |
| Exit to Integer BASIC | E000G | Cold start Integer BASIC | *E000G |
| Exit to Applesoft | E003G | Cold start Applesoft | *E003G |
| Warm Start DOS | 3D0G | Return to DOS without destroying program | *3D0G |
| Cold Start DOS | 3D3G | Restart DOS (clears program) | *3D3G |
| Reset | CTRL+RESET | Hardware reset | - |
Memory Examination Commands
| Command | Syntax | Description | Example |
|---|---|---|---|
| Display Byte | addr | Display single byte | *300 0300- A9 |
| Display Range | addr.addr | Display memory range | *300.31F 0300- A9 00 85... |
| Display Next | (just press Return) | Display next 8 bytes | * 0308- 00 00 00... |
| Display Page | addr.addr | Display full page | *300.3FF |
| ASCII Display | (automatic) | Shows ASCII on right side | *300.30F 0300- C1 D0 D0 CC C5 APPLE |
Display Format
*800.807
0800- A9 00 AA 20 EF FF E8 60 .. ....`
↑ ↑ ↑
Address Hex bytes ASCII
Memory Modification Commands
| Command | Syntax | Description | Example |
|---|---|---|---|
| Store Byte | addr:byte | Store single byte | *300:A9 |
| Store Multiple | addr:b1 b2 b3... | Store multiple bytes | *300:A9 00 85 06 |
| Modify Mode | addr:byteReturn | Enter modify mode | *300:A9 *301:_ |
| Previous in Modify | ← or - | Go back one byte | *301:← *300:A9 |
| Next in Modify | → or Space | Go forward one byte | *300:A9 Space *301:_ |
| Exit Modify | Return | Exit modify mode | *301:Return * |
| ASCII Entry | addr:"text" | Enter ASCII text (with high bit set) | *300:"HELLO" |
Use period (.) to separate addresses in ranges, colon (:) to store data
Execution Commands
| Command | Syntax | Description | Example |
|---|---|---|---|
| Go/Run | addrG | Execute from address | *300G |
| Jump | addrJ | JMP to address | *300J |
| Trace | addrT | Single-step execution | *300T |
| Step | addrS | Step over subroutine | *300S |
| Continue | CTRL+Y | Continue from breakpoint | ^Y |
| Call Subroutine | addrCTRL+E | JSR to address | *FD8E^E |
Execution Notes
- G - Starts execution and doesn't return unless program does RTS to monitor
- J - Same as G but displays registers first
- T - Executes one instruction and shows registers (trace mode)
- S - Steps over JSR calls (executes whole subroutine)
Arithmetic Operations
| Command | Syntax | Description | Example |
|---|---|---|---|
| Add | addr+addr | Add two addresses | *1000+80 1080 |
| Subtract | addr-addr | Subtract addresses | *1000-80 0F80 |
| Hex to Dec | =addr | Convert hex to decimal | *=FF 255 |
| Dec to Hex | =+decimal | Convert decimal to hex | *=+255 00FF |
| Two's Complement | =-addr | Calculate two's complement | *=-1 FFFF |
The monitor uses 16-bit arithmetic for all calculations
Move & Verify Commands
| Command | Syntax | Description | Example |
|---|---|---|---|
| Move Memory | dest<start.endM | Move/copy memory block | *4000<300.3FFM |
| Verify | dest<start.endV | Compare memory blocks | *4000<300.3FFV |
| Fill Memory | start.end:byte | Fill range with byte | *300.3FF:00 |
| Search Memory | start<byte byte...S | Search for byte pattern | *300<A9 00S |
Move Command Details
*4000<300.3FFM ; Copy $300-$3FF to $4000-$40FF
*800<300.3FFM ; Copy $300-$3FF to $800-$8FF
Note: Source and destination can overlap
Register Display & Modification
| Command | Syntax | Description | Example |
|---|---|---|---|
| Display All | CTRL+E | Display all registers | *^E A=00 X=00 Y=00 P=30 S=F8 |
| Set Accumulator | A:value | Set A register | *A:FF |
| Set X Register | X:value | Set X register | *X:01 |
| Set Y Register | Y:value | Set Y register | *Y:80 |
| Set Status | P:value | Set processor status | *P:30 |
| Set Stack Ptr | S:value | Set stack pointer | *S:FF |
Status Register Flags
Bit 7
N - Negative
Bit 6
V - Overflow
Bit 5
- - Unused (always 1)
Bit 4
B - Break
Bit 3
D - Decimal
Bit 2
I - Interrupt Disable
Bit 1
Z - Zero
Bit 0
C - Carry
Input/Output Commands
| Command | Syntax | Description | Example |
|---|---|---|---|
| Input from Keyboard | I | Input hex byte from keyboard | *300:I (type two hex digits) |
| Output to Screen | O | Output ASCII character | *300:41 O A |
| Control Output | CTRL+K | Set output hook | *^K |
| Normal Output | N | Reset to normal I/O | *N |
| User Vector | addrU | Set user command vector | *300U |
Mini-Assembler (! Command)
| Command | Description | Example |
|---|---|---|
| ! | Enter mini-assembler | *! !_ |
| addr:opcode | Assemble instruction | !300:LDA #$00 |
| Return | Next address | !302:_ |
| $ | Exit assembler | !$ * |
Mini-Assembler Examples
*! ; Enter mini-assembler
!300:LDA #$00 ; A9 00
!STA $06 ; 85 06 (auto-increments)
!INX ; E8
!RTS ; 60
!$ ; Exit to monitor
*300L ; Disassemble to verify
0300- A9 00 LDA #$00
0302- 85 06 STA $06
0304- E8 INX
0305- 60 RTS
The mini-assembler supports standard 6502 mnemonics and addressing modes
SWEET16 Commands
SWEET16 is a 16-bit virtual machine interpreter built into Apple II ROM
| To Use SWEET16 | Description |
|---|---|
| 300:20 00 F8 | JSR $F800 - Enter SWEET16 |
| 303:(SWEET16 code) | Place SWEET16 opcodes |
| xxx:00 | RTN - Return to 6502 |
SWEET16 Registers
- R0-R15: Sixteen 16-bit registers
- R0: Accumulator
- R12: Subroutine stack
- R13: Comparison results
- R14: Status register
- R15: Program counter
Useful ROM Monitor Routines
| Address | Name | Function | Registers Used |
|---|---|---|---|
| $F800 | SWEET16 | Enter SWEET16 interpreter | All |
| $F819 | SET | Set SWEET16 register | - |
| $F831 | LD | Load SWEET16 register | - |
| $F941 | PRNTAX | Print A and X in hex | A, X |
| $F944 | PRBLNK | Print 3 spaces | X=3 |
| $F948 | PRBL2 | Print X spaces | X |
| $FA62 | RTS1 | Do RTS | - |
| $FAA6 | OLDRST | Old reset entry | All |
| $FB1E | PREAD | Read paddle | X |
| $FB2F | INIT | Initialize text screen | A |
| $FB39 | SETTXT | Set text mode | - |
| $FB40 | SETGR | Set graphics mode | - |
| $FB60 | SCRN | Read text screen | A, X, Y |
| $FBC1 | BASCALC | Calculate text base address | A |
| $FBD9 | BELL1 | Ring bell | A |
| $FBE4 | BELL2 | Ring bell twice | A |
| $FC22 | VTAB | Vertical tab to A | A |
| $FC24 | VTABZ | Vertical tab to CV | - |
| $FC42 | CLREOP | Clear to end of page | Y |
| $FC58 | HOME | Clear screen | A, Y |
| $FC62 | CR | Carriage return | A |
| $FC66 | LF | Line feed | A |
| $FC9C | CLREOL | Clear to end of line | Y |
| $FCA8 | WAIT | Delay 1/2(26+27A+5A²) μs | A |
| $FD0C | RDKEY | Read keyboard | A |
| $FD1B | KEYIN | Read keyboard (no cursor) | A |
| $FD35 | RDCHAR | Read char with cursor | A |
| $FD6A | GETLN | Get line of input | A, X |
| $FD6F | GETLNZ | Get line (use prompt) | A, X |
| $FD8E | CROUT | Output carriage return | A |
| $FDA3 | PRBYTE | Print byte in hex | A |
| $FDDA | PRHEX | Print nibble in hex | A |
| $FDE3 | PRNTYX | Print Y and X in hex | Y, X |
| $FDED | COUT | Output character | A |
| $FDF0 | COUT1 | Output to screen | A |
| $FE2C | MOVE | Move memory | A, Y |
| $FE5E | LIST | Disassembler | A, X, Y |
| $FE80 | SETINV | Set inverse text | - |
| $FE84 | SETNORM | Set normal text | - |
| $FEB0 | SETVID | Set video mode | - |
| $FEC5 | WRITE | Write cassette tape | A, Y |
| $FECC | READ | Read cassette tape | A, Y |
| $FF3A | BELL | Ring bell | - |
| $FF59 | BRKVEC | BRK vector location | - |
| $FF65 | MON | Enter monitor | All |
| $FF69 | MONZ | Enter monitor quietly | All |
| $FF70 | TRACE | Trace one instruction | All |
Important Memory Locations & Vectors
| Address | Name | Description |
|---|---|---|
| $0020-$002F | WNDLFT/TOP/WIDTH/BTM | Text window parameters |
| $0024 | CH | Horizontal cursor position |
| $0025 | CV | Vertical cursor position |
| $0026-$0027 | GBASL/H | Graphics base address |
| $0028-$0029 | BASL/H | Text base address |
| $0033 | PROMPT | Monitor prompt character |
| $0036-$0037 | CSW | Character output hook |
| $0038-$0039 | KSW | Keyboard input hook |
| $003A-$003B | PCL/H | Program counter storage |
| $003C-$003D | A1L/H | Monitor work area |
| $003E-$003F | A2L/H | Monitor work area |
| $0040-$0041 | A3L/H | Monitor work area |
| $0042-$0043 | A4L/H | Monitor work area |
| $0045 | ACC | Accumulator storage |
| $0046 | XREG | X register storage |
| $0047 | YREG | Y register storage |
| $0048 | STATUS | Status register storage |
| $0049 | SPNT | Stack pointer storage |
| $0050-$00FF | STACK | 6502 stack area (grows down from $01FF) |
| $0200-$02FF | INBUF | Input buffer |
| $03F0-$03F1 | BRKV | BRK vector (normally $FA59) |
| $03F2-$03F3 | SOFTEV | Soft entry vector (normally $FF59) |
| $03F4 | PWREDUP | Power-up byte |
| $03F5-$03F7 | USRV | User command vector (JMP) |
| $03F8-$03FA | NMI | NMI vector (JMP) |
| $03FB-$03FD | IRQV | IRQ vector (JMP) |
| $FFFA-$FFFB | NMIVEC | NMI hardware vector |
| $FFFC-$FFFD | RESETV | RESET hardware vector |
| $FFFE-$FFFF | IRQVEC | IRQ hardware vector |
Monitor Tips & Tricks
Quick Disassembly: Use addrL to disassemble 20 instructions starting at addr
Memory Search: To find a byte sequence, use the Search command: *800<A9 00 85S
Breakpoints: Replace an instruction with BRK ($00) to create a breakpoint. Original byte saved at $49
Quick Fill: Fill memory with zeros: *300.3FF:0
Save Typing: After entering an address once, subsequent commands use it as default
ASCII Text: View memory as ASCII by looking at the right side of the display
Register Shortcut: Just press ^E to see all registers quickly
Modify Memory: Use Space to advance, minus to go back while modifying
Hex Math: Monitor supports 16-bit addition and subtraction directly
Call ROM: Many ROM routines can be called directly, e.g., *FC58G to clear screen
Common Monitor Workflows
1. Write and test a small routine:
*300:A9 00 ; LDA #$00
*302:85 06 ; STA $06
*304:60 ; RTS
*300L ; Disassemble to verify
*300G ; Run it
2. Save memory to cassette (old school!):
*800.8FFW ; Write $800-$8FF to tape
*800.8FFR ; Read it back
3. Examine and modify a BASIC program:
*67.68 ; See program start pointer
*800.9FF ; View program area
4. Debug with breakpoints:
*305 ; See what's at $305
*305:00 ; Replace with BRK
*300G ; Run until breakpoint
*^E ; Check registers
*305:XX ; Restore original byte
*^Y ; Continue execution
Historical Note: The Apple II System Monitor, written by Steve Wozniak, fit in just 2KB of ROM and provided a complete development environment. Its compact design and powerful features made it legendary among early microcomputer monitors.