SearchA-ZH › Hack

Hack

2026 Open source · Public domain Online

An authored, in-browser Hack computer - the 16-bit teaching machine from "The Elements of Computing Systems" (nand2tetris). It has two 16-bit registers (A and D) plus M = RAM[A], an instruction ROM, and a 16-bit data RAM whose 16384..24575 window is the 512x256 monochrome SCREEN and whose 24576 word (KBD) is the keyboard. It boots running an animated screen-fill program and plugs into the shared debugger, so you can single-step one instruction, set breakpoints on a ROM address, watch a RAM address, and type on the keyboard.

Visit the official site ↗

Runs on: Web browser

Hack Online Emulator

Play Hack using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Animated screen fillHackopenOpen ⛶

Notes

Embedding

The Hack computer here is authored from scratch in one small file, hack.js. It is a plain global - Hack.create(canvas) returns a machine object whose whole state is ordinary JavaScript, so the debugger reaches straight into it with no wasm heap or hidden loop.

Boot. Assemble a program with the bundled tiny assembler and load it into the ROM, then run your own loop built on hack.step() (execute exactly one instruction):

var hack = Hack.create(canvas);
hack.load(Hack.assemble('@SCREEN\nD=A\n...'));   // dest=comp;jump source -> ROM
(function loop(){
  hack.step();                            // one instruction
  hack.render();
  requestAnimationFrame(loop);
})();

The machine is plain fields. Everything the debugger needs is live on the object:

MemberKindWhat it does
hack.step()methodFetch, decode and execute one instruction. The single-step primitive.
hack.A · hack.D · hack.pcfieldsThe two 16-bit registers and the 15-bit program counter, read and written live.
hack.rom · hack.ramfieldsThe instruction ROM and the 16-bit data RAM (the 16384..24575 window is the screen; 24576 is KBD).
hack.peek(a) · hack.poke(a,v)methodsSide-effect-free read / write of a RAM word, used by the debugger's memory views.
hack.kbSet(code)methodWrite a Hack key code into RAM[24576] (the keyboard register).
Hack.assemble(src)staticAssemble @value and dest=comp;jump source into a ROM image.

Because the registers, ROM and RAM are ordinary JavaScript, breakpoints are a host-side Set of PC values checked before each step(), and watchpoints are checked inside poke - no changes to the core.

Debugger integration

The boot shim publishes window.EMU_BOOT with a full transport: pause / resume / isPaused, stepInsn(n) (one instruction), step(n) (a burst), reset, plus breakpoints (a Set of ROM addresses the loop checks before each step) and watchpoints (a Set of RAM addresses, checked inside poke). A CPU decoder - /debugger/src/cpus/hack.js - turns each ROM word back into @value or dest=comp;jump. It reads the true 16-bit word off EMU_BOOT.hack.rom, because the shared views hand decoders a byte-masked reader that would truncate a word.

Architecture

The Hack computer is the target machine of "The Elements of Computing Systems" (nand2tetris), small enough to build from NAND gates, complete enough to run real programs:

  • Registers A and D - two 16-bit registers. M is the pseudo-register RAM[A]: the memory word the A register currently points at.
  • Instruction ROM - 16-bit instructions, one per word, addressed by the 15-bit program counter PC.
  • Data RAM - 16-bit words. RAM[16384..24575] is the 512x256 monochrome SCREEN (each word is 16 horizontal pixels); RAM[24576] is the keyboard (KBD).

There are two instruction kinds:

PatternKindEffect
0vvvvvvvvvvvvvvvA-instructionA ← v (a 15-bit constant)
111a cccccc ddd jjjC-instructionALU computes comp from D and (A or M); dest latches it into A/D/M; jump compares it to 0 and may set PC ← A.

The shared debugger's hack decoder turns each ROM word back into @value or dest=comp;jump, so you can watch the fetch-decode-execute cycle one instruction at a time.