Skip to content
Lesson 3 of 13

Step 1 of 5 · Reading · ~3 min

Read

CHIP-8 Architecture

Fetch-Decode-Execute

Every CPU ever built does the same three things forever: fetch the next instruction, work out what it means, do it. This lesson is the first two. After it your program can take the raw bytes of a real ROM and tell you what each instruction is, which is exactly what a disassembler does, and it is the front half of the emulator.

Fetch: two bytes, high first

An instruction is two bytes at the address in PC. The byte at PC is the high half, so the word is (byte at PC) * 256 + (byte at PC+1). The bytes 6A 02 are the word 0x6A02; read backwards they would be 0x026A, a completely different instruction. After the fetch PC moves up by 2 so it names the next instruction. Fetching never looks at what the bytes mean.

Decode: the word is four nibbles

Write the word as four hex digits, H X Y N. Most instructions use them like this:

0x D 3 A 7
   | | | +-- N    low nibble: a count or a sub-opcode
   | | +---- Y    a register number, V0..VF
   | +------ X    a register number
   +-------- H    the family of instruction

KK  = low byte  (0xA7)     an 8-bit constant
NNN = low 12 bits (0x3A7)  an address

You get a nibble by shifting right and masking with 0xF: the third digit is the word shifted right by 4, then ANDed with 0xF. KK is the word ANDed with 0xFF, NNN the word ANDed with 0xFFF. D3A7 is family D with X = 3, Y = A, N = 7: draw 7 rows at the position held in V3 and VA.

The instruction set in one table

Dispatch on H first. Seven families need a second look because their meaning lives in the low digits.

0NNN  ignored system call     except 00E0 clear screen, 00EE return
1NNN  jump          2NNN  call          BNNN  jump to NNN + V0
3XKK  skip if VX == KK        4XKK  skip if VX != KK
5XY0  skip if VX == VY        9XY0  skip if VX != VY
6XKK  VX = KK       7XKK  VX += KK      ANNN  I = NNN
8XYn  ALU: n = 0 move, 1 or, 2 and, 3 xor, 4 add, 5 sub,
           6 shift right, 7 reversed sub, E shift left
CXKK  VX = random AND KK       DXYN  draw N rows at (VX, VY)
EX9E  skip if key VX down      EXA1  skip if key VX up
FX07  VX = delay timer         FX0A  wait for a key into VX
FX15  delay timer = VX         FX18  sound timer = VX
FX1E  I += VX       FX29  I = font digit VX       FX33  decimal digits of VX
FX55  store V0..VX  FX65  load V0..VX

Two traps hide in that table. In 5XY0 and 9XY0 the last digit must be 0; 5AB1 is not a valid instruction. In the E and F families the identity is the whole low byte, not the low nibble: E19E is a skip, E19F is nothing. Treat anything the table does not list as unknown.

Common mistakes

  • Reading the two bytes in the wrong order.
  • Dispatching on H alone, so 5AB1 and E19F look valid.
  • Taking N from the wrong digit. X is the second digit, Y the third, N the fourth.
  • Forgetting that 0NNN is a family of its own: everything starting with 0 except 00E0 and 00EE is a system call.
  • Ignoring a trailing odd byte: a file may end in the middle of a word.

Your exercise

The input is a ROM as a hex dump. You print one line per instruction: its address, the word, and a name for it. The starter reads the bytes and prints the lines; you write decode, which turns one word into text. The IBM logo from the next lessons is one of the tests.

Up nextALU & Skip InstructionsInstructions

Discussion

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

Sign in to post a comment or reply.

Loading…