Skip to content

The memory map in full

Sixty-four kilobytes of address space, and every one of them is already spoken for. Here is who owns what.

The whole thing at a glance

FromToWhat's there
$0000$00FFZero page
$0100$01FFCPU stack
$0200$02FFKeyboard ring buffer
$0300$03FFKernal variables
$0400$05FFBASIC line buffers
$0600$07FFCompactFlash sector buffer
$0800$7FFFProgram RAM
$8000$9FFFThe eight hardware slots
$A000$B7FFThe Kernal — jump table, then the routines behind it
$B800$BFFFThe character set
$C000$EDFFBASIC
$EE00$FEFFThe Monitor
$FF00$FFF9Wozmon
$FFFA$FFFFThe processor's NMI, reset and interrupt vectors

The bottom 32 KB is RAM, the top 24 KB is ROM, and the eight kilobytes between them are where the cards live — one kilobyte each.

$8000 is not memory

Reading or writing an address in the hardware window talks to a chip, not to storage. A stray write there can change the screen mode, retune a voice, or select a different bank of RAM. Everything in this range is described in What's fitted.

Zero page

The first 256 bytes, where every access is a byte shorter and a cycle faster.

FromToWhose
$00$39The Kernal's — pointers, filesystem and transfer state, Monitor scratch
$3A$FFYours. 198 bytes.

Which means it is yours once your program is the thing running. Underneath a running BASIC the interpreter is using that space as it goes, so a BASIC program that poked a value into zero page would find it gone a moment later. Machine code loaded and started from BASIC is fine: BASIC is sitting still while you run.

What the Kernal keeps down there
AddressNameWhat it's for
$00ZP
$00READ_PTR
$01WRITE_PTR
$02STR_PTRString pointer (2 bytes)
$24CF_BUF_PTRCF sector data buffer pointer (2 bytes)
$26CF_LBACF 28-bit LBA address (4 bytes, little-endian)
$2AXFER_PTRSerial transfer data pointer (2 bytes)
$2CDELAY_CNTSysDelay 16-bit centisecond counter
$2EMON_ADDRMonitor current address (2 bytes)
$36XMODEM_BLKXModem expected/current block number
$37XMODEM_CHKXModem running checksum
$38XMODEM_RETRYXModem retry counter
$39XMODEM_RCVBLKXModem received block number
$30MON_ENDMonitor end address (2 bytes)
$32MON_TMPMonitor temp pointer (2 bytes)
$34MON_BYTEMonitor parsed byte scratch
$35MON_IDXMonitor input line index
The 256 bytes of zero page, showing which are the Kernal’s and which are yours Zero page, byte by byte 0 1 2 3 4 5 6 7 8 9 A B C D E F $00 $10 $20 $30 $40 $50 $60 $70 $80 $90 $A0 $B0 $C0 $D0 $E0 $F0 $00–$39 — the Kernal, BASIC, the Monitor and XModem $3A–$FF — 198 bytes, yours
The Kernal has the first fifty-eight bytes. The other 198 are yours, and they are the fastest memory on the machine.

The rest of the low RAM

$0100–$01FF — the stack. 256 bytes, growing down from $01FF. BASIC keeps its FOR and GOSUB frames here too, which is why deep nesting runs out of memory rather than slowing down.

$0200–$02FF — the keyboard ring buffer. Keys and serial bytes land here the moment they arrive, put there by the interrupt handler. Chrin takes them out again.

$0300–$03FF — the Kernal's variables. Interrupt vectors, the cursor, what hardware was found, the current disk, the cartridge boot vector. The named ones you are most likely to want are below.

$0400–$05FF — BASIC's line buffers. The raw line you typed and the tokenized version of it.

$0600–$07FF — the card sector buffer. 512 bytes, and any filesystem call overwrites it. It is tempting free memory when BASIC is not doing anything, and it is a trap the first time your program saves a file.

$0800–$7FFF — yours. About 30 KB. A .prg loads at $0800; a BASIC program lives there too, which is why the two cannot be resident at once.

The Kernal's variables

AddressNameWhat it's for
$0300KERNAL_VARS
$0300IRQ_PTR
$0302BRK_PTR
$0304NMI_PTR
$0306IO_MODEBit 0: 0=video, 1=serial output
$0307VID_CURSOR_XVideo cursor column (0-39)
$0308VID_CURSOR_YVideo cursor row (0-23)
$0309VID_CURSOR_ADDRVideo cursor VRAM address ($0309-$030A)
$030BRTC_BUF_CENTCentury value from last RtcReadDate / for RtcWriteDate
$030CRTC_TMPScratch byte for BCD conversion
$030DHW_PRESENTHardware present bitmask (set during Reset probe)
$030EBAS_PENDKEYPending key from BasCheckBreak (1 byte)
$030FCF_DISKCurrent CF "disk" bank (0-255); base LBA = CF_DISK * FS_DISK_SECTORS
$0310BRK_PSaved P at time of BRK
$0311BRK_PCLSaved PCL at time of BRK (points to BRK+2)
$0312BRK_PCHSaved PCH at time of BRK
$0313BRK_ASaved A at time of BRK
$0314BRK_XSaved X at time of BRK
$0315BRK_YSaved Y at time of BRK
$0316BRK_SPSaved SP at time of BRK
$0317XFER_REMAINRemaining bytes to transfer (2 bytes)
$0319XFER_IO_SAVESaved IO_MODE before switching to serial
$031ABAS_DATAPTRDATA read position (2 bytes)
$031CBAS_STOPLINESaved BAS_CURLINE for CONT (2 bytes)
$031EBAS_STOPTXTSaved BAS_TXTPTR for CONT (2 bytes)
$0320SCROLL_BUF40-byte scroll temp buffer
$0348FS_START_SECFile start sector (2 bytes)
$034AFS_FILE_SIZEFile size in bytes (2 bytes)
$034CFS_SEC_COUNTNumber of sectors to read/write
$034DFS_DIR_IDXDirectory entry index (0-15)
$034EFS_NEXT_SECNext free sector for allocation (2 bytes)
$0350FS_FNAME_BUF11-byte filename buffer (8 name + 3 ext)
$035BBOOT_VECTORCart/boot redirect vector (2 bytes, 0=normal boot)
$035DBAS_TXTTABStart of program text (= $0800)
$035FBAS_VARTABEnd-of-program / start-of-vars pointer
$0361BAS_ARYTABStart of arrays
$0363BAS_STRENDEnd of arrays
$0365BAS_FRETOPTop-of-string-heap pointer
$0367BAS_MEMSIZEnd of usable memory (= $8000)
$0369BAS_CURLINCurrently executing line ($FFFF=direct mode)
$036BBAS_OLDLINSaved line for CONT
$036DBAS_OLDTEXTSaved text ptr for CONT
$036FBAS_WARMWarm-start magic ($A5 = previously initialized)
$0370BAS_POSXPRINT column counter (0-39 video / 0-79 serial)
$0371BAS_INPSAVSaved TXTPTR across INPUT REDO retry
$0373BAS_FNPTRFN variable slot addr held across FnCall's expression evaluations (out of ZP so FrmEvl/Garbag cannot touch it)
$0375BAS_STKBASEStack pointer the READY loop restores before each direct-mode line: $FF with no
$037FFS_IO_ADDRLoad/save target address for FsLoadFileAddr/FsSaveFileAddr
$0381BAS_FNAME13-byte scratch for null-terminated 8.3 filename (12-char "NAME.EXT" + null)
$038EPRG_IMAGE_ENDEnd address of a program image placed at PROGRAM_START by a loader

The hardware window

Eight slots of one kilobyte each, from $8000 to $9FFF, one per card.

SlotFromToWhat's there
1$8000$83FFAS6C4008 banked SRAM (low)
2$8400$87FFAS6C4008 banked SRAM (high)
3$8800$8BFFDS1511Y
4$8C00$8FFFCompactFlash (8-bit True IDE)
5$9000$93FFR65C51 / W65C51 ACIA
6$9400$97FFW65C22 VIA
7$9800$9BFFMOS 6581 SID / ARMSID
8$9C00$9FFFTMS9918A / Pico9918
The eight I/O slots between $8000 and $9FFF The hardware window, $8000 to $9FFF Eight slots of one kilobyte, one card each $8000 1 RAM Card AS6C4008 banked SRAM (low) $8400 2 RAM Card AS6C4008 banked SRAM (high) $8800 3 RTC Card DS1511Y $8C00 4 Storage Card CompactFlash (8-bit True IDE) $9000 5 Serial Card R65C51 / W65C51 ACIA $9400 6 GPIO Card / Input Board W65C22 VIA $9800 7 Sound Card MOS 6581 SID / ARMSID $9C00 8 Video Card / VGA Card TMS9918A / Pico9918 The Reset probe writes one bit per slot to $030D, in slot order. MEM prints it as HW=$xx; from BASIC it is PEEK(781).
One kilobyte per slot, in the order the detection bits come in. A card that is not fitted leaves its slot reading nothing in particular — which is what HW_PRESENT is for.

The ROM

The first 256 bytes of the Kernal are the jump table — the only addresses in the whole ROM you should ever write down. $B800 upwards is the character set, which is worth knowing about because you can read it, copy it, and change it (The screen).

$FF00 is Wozmon, Steve Wozniak's 256-byte monitor from the Apple I, kept because it fits and because it is a lovely thing to have.

The 64K address space, from zero page to the processor vectors The 64K address space $FFFF Vectors $FFFA 6 bytes Wozmon $FF00 250 bytes Monitor $EE00 4.3 KB BASIC $C000 11.5 KB Character set $B800 2 KB Kernal $A000 6 KB Eight I/O slots $8000 8 KB Program RAM $0800 30 KB CompactFlash sector buffer $0600 512 bytes BASIC line buffers $0400 512 bytes Kernal variables $0300 256 bytes Keyboard ring buffer $0200 256 bytes CPU stack $0100 256 bytes Zero page $0000 256 bytes RAM I/O ROM Your program loads at $0800. Everything from $8000 up is cards and ROM.
The whole 64K, bottom to top. The bands are not to scale — at 64K in a page-height strip, zero page would be two pixels.

Next: the Kernal — the routines that live in that ROM.

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