Memory

What is memory?

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 a!

    ; 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 [$C000] does.

Now, you have to use a with [bc] and [de], but [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.

Endianness

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?