Skip to content

A Street of Numbered Boxes

Meet memory — a street of numbered boxes, each holding a byte. Store a byte at an address and read it back, the same round-trip you used for registers. And learn why the NES's street is far shorter than you'd guess.

  • Nintendo Entertainment System
  • Assembly

A byte in a register is a byte you’re holding in your hand. But there are only three registers, and you can’t put a whole game in your hands. So where do bytes live the rest of the time?

In memory. Picture a street of numbered boxes, each with an address — just a number, like a house number — holding exactly one byte. You write a byte into a free box and read it back whenever you like. You met this in BASIC through a side door — POKE to write a box, PEEK to read one. Here it’s your main tool, and it’s two ordinary instructions.

But here’s the first place the NES surprises a C64 programmer: its street is short. The 2A03 can name 65,536 addresses, like any 6502 — but the NES only wires up 2 KB of actual RAM, the boxes from $0000 to $07FF. That’s all the free workspace you get. The rest of the address range isn’t yours: $8000 and up is the cartridge ROM (you can read your program there, but you can’t store into it), and the ranges around $2000 and $4000 are hardware — the PPU and the sound and controller chips. Write there and you change the machine, not memory. Two kilobytes sounds tiny, and it is; NES games learn to be frugal.

What you’ll see by the end

The NES screen filled with solid green.
A green screen proving a round trip: the value $2a stored out to a memory box, the register wiped, then fetched back from the box.

A green screen — value $2a. But as in Unit 2, the colour isn’t the point: this value went out into memory and came back. We stored it at a box, wiped the register clean, then fetched it from the box again. The screen is the proof; the real evidence is in the memory view — watch box $0300 fill with $2a.

Store and read: two mirror-image instructions

Instruction Means
sta $0300 store — put A’s byte into the box at address $0300
lda $0300 read — fetch the box at $0300 back into A

You already know lda — earlier it loaded a value (lda #$2a). Here it loads from a box (lda $0300). The difference is that little #: #$2a means the number $2a; plain $0300 means the box at address $0300. Forget the # and you load the contents of address $2a instead of the number — a mix-up worth meeting now, because it’s the most common one there is.

It’s the same round trip you ran for registers in Unit 2 — but the value travels out to a memory box and back, instead of into X:

After… A box $0300
lda #$2a $2a —
sta $0300 $2a $2a
lda #$00 $00 $2a
lda $0300 $2a $2a

The program

Same sealed harness; the YOUR CODE block is the round trip:

boxes.asm
; ============================================================================
; Meet the Machine (NES) - Unit 4: A Street of Numbered Boxes
;
; Same sealed harness - it shows whatever colour you leave in A. This time the
; value takes a round trip out to a box in memory and back, to prove the box
; held it. The NES has only 2 KB of these boxes: $0000 to $07FF.
; ============================================================================

.segment "HEADER"
    .byte "NES", $1a
    .byte 2
    .byte 1
    .byte $00, $00

.segment "CODE"

reset:
    sei
    cld
    ldx #$40
    stx $4017
    ldx #$ff
    txs
    inx
    stx $2000
    stx $2001
    stx $4010
warm1:
    bit $2002
    bpl warm1
warm2:
    bit $2002
    bpl warm2

    ; ----------------------------------------------------------- YOUR CODE START
    lda #$2a                ; A = $2a (a green)
    sta $0300               ; store A into the box at $0300
    lda #$00                ; wipe A clean
    lda $0300               ; read the box back into A
    ; ------------------------------------------------------------- YOUR CODE END

    sta $00
    bit $2002
    lda #$3f
    sta $2006
    lda #$00
    sta $2006
    lda $00
    sta $2007

forever:
    jmp forever

nmi:
    rti
irq:
    rti

.segment "VECTORS"
    .word nmi
    .word reset
    .word irq

.segment "CHARS"
    .byte $00,$00,$00,$00,$00,$00,$00,$00
    .byte $00,$00,$00,$00,$00,$00,$00,$00
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
    .byte $00,$00,$00,$00,$00,$00,$00,$00
    .res 8192 - 32, $00

We wipe A to 0 between storing and reading, so the green screen can only mean the $2a came back from memory. sta $0300 is your POKE; lda $0300 is your PEEK.

Assemble and run

Code
ca65 boxes.asm -o boxes.o && ld65 -C nes.cfg boxes.o -o boxes.nes

Load it with the memory view open, and watch box $0300 take the $2a before the screen turns green.

Try this: any free box will do

Change both $0300s to another free RAM address — say $0310. Same green screen. Nothing is special about $0300; any box from $0000 to $07FF holds your byte just as well. (Steer clear of three areas: $0000, which the harness borrows as scratch; $0200, which games reserve for sprites; and anything from $2000 up, where the hardware and the cartridge live — that’s not free RAM.)

Try this: store past the end of RAM

Change the store to sta $4000 — an address the NES can name, but one that belongs to the sound hardware, not RAM. Assemble and run. The screen does not come up green: the $2a never lands in a box you can read back, because $4000 isn’t memory — it’s a register on the APU, and writing there does something else entirely. The lesson: only $0000–$07FF behaves like the street of boxes. Put $0300 back.

If it doesn’t work

  • The screen is black, not green. The lda $0300 read is missing or mistyped, so A was still 0 from the wipe. Check there’s no # on it — lda $0300, not lda #$0300.
  • ca65 complains about the store. Check it’s sta $0300 (no #). With the # it’s not a valid store at all.
  • Nothing in the memory view changes. Make sure you’re looking at $0300 in the 2 KB RAM window, not somewhere up in the cartridge range.

What you’ve learnt

Memory is a street of numbered boxes, each holding one byte: sta addr stores A’s byte at an address, lda addr reads it back, and the # is what separates a number from the box at that number. On the NES only $0000–$07FF is real RAM — a frugal 2 KB.

What’s next

Some addresses aren’t quiet boxes at all — write to the right ones and you change what’s on the screen. But on the NES the screen doesn’t sit in this street the way it does on a home computer. Next — The Screen Is Behind a Window — we finally open up that harness line that’s been painting your colour, and meet the PPU.

Run it here

This unit's program, built for you.

Program
boxes.nes
Machine
Nintendo NES (NTSC)

Download boxes.nes