PlayMMIX — MMIX in the Browser
Posted on Sat 05 September 2026 in tech
An MMIX playground, playmmix, puts an MMIX machine in your browser with no install, no local setup, no build step.
MMIX is Knuth's 64-bit RISC architecture. I built checksmix to assemble and run programs for it. playmmix wraps that same engine with an editor and a live debugger, in Rust, Yew and WebAssembly.
Editing the source re-assembles and reloads the machine at its entry point, the same
way mmixdb does — but nothing executes until you click Run.

Driving the MMIX machine
Five controls drive execution:
- Run executes until the program halts or hits a breakpoint.
- Step executes one source-level step, following calls into the callee.
- Step Over runs a call until it returns, unless a breakpoint or halt stops it first.
- Stop interrupts execution where it is.
- Reset reloads the current source, clearing output and change highlights.
Click a line number to set a breakpoint on an instruction. The machine pane highlights values that changed since the previous pause. Step once and see what moved; run to a breakpoint and see what changed along the way.
Testing a small prime
Trial division tries D = 2, 3, 4, … against N. If D divides N, N is composite. If D * D exceeds N first, N is prime.
Paste this into playmmix:
LOC #100
Main SETL $1,97 # N
PUSHJ $0,IsPrime # $0 = 1 if prime, 0 if composite
XOR $255,$0,1 # exit 0 if prime, 1 if composite
TRAP 0,Halt,0
IsPrime CMPU $1,$0,2
BN $1,Composite # 0 and 1 are not prime
SETL $1,2 # D
Loop MULU $2,$1,$1
CMPU $2,$2,$0
BP $2,Prime # D * D > N
DIVU $2,$0,$1
GET $2,rR # N mod D
BZ $2,Composite
ADDU $1,$1,1
JMP Loop
Prime SETL $0,1
POP 1,0
Composite SETL $0,0
POP 1,0
Click Run. The program exits 0, prime: the loop tries 2 through 9 and stops at 10, since 100 exceeds 97. Change 97 to 91 and run again: it exits 1, composite, found at 7.
This program is using remark-style comments that are documented in The Art of Computer Programming, Volume 1, Fascicle 1, Section 1.3.2´. An MMIX statement is made up of a LABEL, OP and EXPR. Everything to the right of EXPR is considered a comment, unless it starts with a digit or an operator. This has the funny consequence that the # is entirely irrelevant and used here to orient the eye.
Following the call
Put 97 back and click Reset. One click on Step loads N into $1. The
next instruction is PUSHJ $0,IsPrime.
Click Step again. Now we're at IsPrime, call depth is 1, and N is in $0.
Set a breakpoint on Loop and click Run. $1, which holds D, reads 2.
Each Run stops at the next pass. D climbs and N stays put; at 10, 10 * 10
passes 97 and BP goes to Prime.
Reset, Step once and choose Step Over on the PUSHJ. Execution
stops at Loop. Click the line number to remove the breakpoint and Run:
IsPrime returns and the program halts. With no breakpoint set, Step Over steps
over IsPrime and pauses at the XOR with $0 = 1.
Getting home
PUSHJ writes the return address to the special register rJ. POP 1,0
returns one value, placing the callee's $0 in Main's $0, the register its
PUSHJ named. The
MMIX instruction reference
has the full register-stack rules.
Under the hood
checksmix is the assembler and the emulator with registers,
memory and TRAP handling. playmmix uses its public MMixAssembler and MMix
APIs. The editor, execution controls and machine display live in playmmix.
Re-assembly pauses for half a second after typing stops, so an unfinished line doesn't flash an error on every keystroke. Run and Step flush any pending edit before executing. A successful assembly starts a fresh machine.
Step Over doesn't skip the call. It single-steps through the callee automatically, checking the call depth after every instruction until execution returns to where it started. That's also why a breakpoint set inside the callee still fires even under Step Over: the same per-instruction check Run relies on applies here too.
Long runs execute in bounded chunks, yielding to the browser between them. That keeps Stop available, including while Step Over is working through a call. The arithmetic runs locally in WebAssembly.
For .mmo object files or a shell, use
checksmix, also available on
crates.io. Its command-line debugger,
mmixdb, has its own worked example.
Open playmmix, paste the program, and try 49. Watch which branch it takes when the divisor's square equals the number. The source is on GitHub.