Memory is pretty straightforward: it's a field of bytes. Each byte has an address, which is used to access it. Addresses are coded using 16 bits, so the CPU can "see" 65536 bytes at once ($0000-$FFFF). Alert readers will have noticed that this is exactly the same size as a register pair, and will be proven correct further below.
To access memory, we will use our trusty
ld. How do we denote "memory access"? Simple: using square brackets! While
$C000 represents the number $C000,
[$C000] represents the byte at address $C000.
So, you may be tempted to write stuff like
ld d, [$1DEA]. But there's a pretty big catch: this only works with
; This is ok ld [$ABAD], a ld a, [$1DEA] ; This is not ld [$DEAD], l ld bc, [$BEEF]
Pairs, rock out!!
Let's take the bracketing a little further. While
[[$C000]] would have been nice (I can already hear a 6502 mob booing), we have something else. Remember how "
[$C000] represents the byte at address $C000"? Well,
[hl] represents the byte at address
hl. Thus, if
hl = $C000, then
[hl] represents the same byte as
Now, you have to use
[hl] saves the day by being usable with all 8-bit registers! Actually, for almost all purposes,
[hl] can be considered an 8-bit register. Neat!
; Ok ld a, [de] ld [bc], a ; Not ok ld c, [de] ld [de], hl ; Ok ld a, [hl] ld l, [hl] ld [hl], c ; Not ok ld bc, [hl] ld [hl], [hl]
This paragraph is fairly technical for this part of the tutorial, and is useless trivia anyways. You can skip it without danger.
ld [hl], [hl] is not a valid instruction. If you're clever enough to figure out how the
ld reg8, reg8 instructions are encoded, you will figure out that
ld [hl], [hl] should be encoded by the value $76. Thing is, $76 maps to the
halt instruction, so
ld [hl], [hl] really doesn't exist.
Let's consider a simple problem: I have the two-byte value $C0DE that I want to store in memory. I want to store it in two consecutive bytes, obviously, one containing the value $C0, and the other containing the value $DE. So, in which order should I store them? I'm expecting most of the readers to store $C0 first and $DE second, because that's the order we read them in, right? That's called big-endian storage, and... it's not what the GB's CPU uses.
WHAT??!? I hear you say?
You'd use little-endian storage, where $DE is stored first, and $C0 second??? This is madness!!
After avoiding the obvious (Spartan) reference that should have ensued, I will argument that little-endian storage may not be the most intuitive, but it's definitely the most practical, for a reason we will see later. Also, there's nothing preventing you from writing code that uses big-endian storage anyways, but I reeeeally recommend you get used to it -- since the CPU is little-endian, you're going to see that anyways when debugging, so it's better to follow the trend. Trust me, okay?