Skip to content
Lesson 2 of 13

Step 1 of 5 · Reading · ~3 min

Read

CHIP-8 Architecture

Registers & Memory

The CHIP-8 has very little state, and every instruction you write later reads or changes some of it. After this lesson your emulator holds that state correctly: sixteen byte-sized registers that wrap at 256, one carry flag that arithmetic sets, and 4096 bytes of RAM with the hex font already in place.

State

V0 .. VF    16 registers, 8 bits each (0..255)
RAM         4096 bytes, addresses 0x000 .. 0xFFF

The font is 16 sprites, one per hex digit, five bytes each. The interpreter copies it into RAM at 0x050 before any ROM runs. Digit 0 is five rows, each row a byte whose high four bits are the pixels:

F0   ####
90   #..#
90   #..#
90   #..#
F0   ####

The starter gives you the 80 bytes; you place them. Everything below 0x050 and everything above the font stays zero.

8 bits means wrap, not grow

A register cannot hold 256. Adding 200 and 100 gives 300, which is 0x12C, and the register keeps only the low eight bits, 0x2C. Arithmetic on registers always means "compute, then keep the low byte".

Two different additions

CHIP-8 has two ADDs that look alike and are not:

7XKK   VX = VX + KK       add a constant; wraps; VF is NOT touched
8XY4   VX = VX + VY       add a register; wraps; VF = carry

The second one reports overflow: VF becomes 1 when the true sum was above 255 and 0 otherwise, including when a previous instruction left VF at some other value. The first one never touches VF, which is why a ROM can increment a score without disturbing a flag it is still using. A trace of the second kind with numbers this lesson's tests avoid:

V5 = E1 (225)     V6 = 3F (63)
sum  = 225 + 63 = 288 = 0x120
V5   = 0x20       keep the low byte
VF   = 1          the sum did not fit

VF is a register too

VF is just V15. A program may load it, read it, or even name it as the destination of an addition. The rule that makes this work is the order inside 8XY4: read both operands, write the sum to VX, and write VF last. When X is F, the sum lands in VF and the carry then overwrites it, so the program sees 0 or 1. When Y is F, the old VF is used as the operand, because it was read before the flag changed.

How the harness talks to you

This lesson's tests are a list of commands in the notation of the instruction set, one per line, with hex numbers:

LD V3 0A       V3 = 0x0A                 (6XKK)
ADD V3 05      V3 = V3 + 0x05            (7XKK)
ADD V3 V4      V3 = V3 + V4, VF = carry  (8XY4)
DUMP           print V0..VF as 16 two-digit hex bytes
MEM 050 5      print 5 bytes of RAM from address 0x050

An operand that starts with V is a register, anything else is a number.

Common mistakes

  • Forgetting to wrap, so a register holds 300.
  • Letting ADD VX, KK change VF.
  • Setting VF before computing the sum, which corrupts the case X = F and the case Y = F.
  • Leaving VF at 1 when a later addition does not carry. Every 8XY4 writes VF, 0 or 1.

Your exercise

Copy the font into RAM and implement the three register operations. The starter parses the commands and prints; it hands you a machine with empty methods.

Up nextFetch-Decode-ExecuteCHIP-8 Architecture

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…