Step 1 of 5 · Reading · ~3 min
Read
Instructions
Stack & Jumps
After this lesson a ROM can leave the straight line: jump to another address, call a subroutine and come back, and pick a target from a table. Without these a CHIP-8 program is a few dozen instructions that run once. With them it is a loop, and a game is a loop.
Four ways to change PC
1NNN JP NNN PC = NNN
2NNN CALL NNN save PC on the stack, then PC = NNN
00EE RET PC = the most recently saved address
BNNN JP V0, NNN PC = NNN + V0
Addresses are 12 bits, so every new PC is masked to 0x000..0xFFF.
The stack holds return addresses and nothing else
The stack has 16 slots, and each slot holds one address. CALL pushes the current PC. Fetch already moved PC past the CALL, so the saved value is the address of the instruction after the CALL, which is exactly where RET must land. Pushing the address of the CALL itself would make every return call the subroutine again.
Trace of a call, using addresses this lesson's tests do not use:
200: 2208 CALL 208
202: 6301 V3 = 1
204: 1204 JP 204 (jump to itself: the usual way to "stop")
206: 0000
208: 7A05 VA = VA + 5
20A: 00EE RET
step runs PC after stack
1 2208 208 [202]
2 7A05 20A [202]
3 00EE 202 []
4 6301 204 []
5 1204 204 [] (stays here forever)
A jump to its own address never advances, so a ROM that has nothing left to do ends in JP to itself. Emulators and test ROMs rely on it.
Overflow and underflow
Sixteen nested calls fit. The seventeenth does not, and RET with nothing saved has nowhere to go. Real interpreters differ on what happens, so this machine defines it: the instruction does nothing else, the machine records a fault (STACK_OVERFLOW or STACK_UNDERFLOW), and from then on RUN executes nothing. PC stays where fetch left it, just past the faulting instruction, and SHOW adds a third line FAULT= followed by the name.
BNNN: jump tables
BNNN adds V0 to the address. Put a row of two-byte JP instructions at NNN and load V0 with twice the case number; the jump lands on that case's row, which jumps on to the code. It is the CHIP-8 switch statement. (Some later interpreters use BXNN and add VX; that is a quirk for the quirks lesson.)
Common mistakes
- Saving the CALL's own address, so
RETcalls the subroutine again forever. - Allowing a 17th nested call by checking the depth after the push instead of before.
- Letting
RETon an empty stack read a stale slot and jump somewhere random. - Forgetting to mask
NNN + V0, so PC leaves the 4 KB address space. - Continuing to execute after a fault.
Your exercise
The starter already runs everything from the earlier lessons. You add 1NNN, 2NNN, BNNN and 00EE, including the two faults. Test a chain of exactly 16 calls and then a 17th: the boundary is where a stack goes wrong.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…