Search › A-Z › M › Manchester Mark 1
Manchester Mark 1
The Manchester Mark 1 ran at the University of Manchester in 1949, growing out of the SSEM "Baby" of 1948. This is an original implementation, written from scratch for emulators.org. It keeps the Baby’s Williams-Kilburn tube store and single accumulator but adds the features that made it a working computer, several of them world firsts: a wider 40-bit word held on tube pages of 32 lines (backed by a magnetic drum), the B-lines (index registers that modify an instruction’s address — the B-tube), an 80-bit accumulator with a hardware multiplier, and teleprinter output. An instruction carries a 10-bit address, a 3-bit B-line and a 7-bit function.
It boots with a program already running: the factorial series 1! 2! … 10!, each result printed on the teleprinter as its dot pattern is computed on the Williams-tube store. The whole machine — accumulator, control register, the index registers and every store line — is exposed to the shared debugger, so you can single-step the fetch-decode-execute cycle, set breakpoints on a store line, watch a line for writes, and read the program back as a disassembly of the Mark 1 function codes. A second configuration prints a table of squares using a B-line as an index register. An on-screen console gives Run, Stop, Step and Reset; the Mark 1 had switches and hand-keys, not a typewriter keyboard.
Runs on: Web browser
Manchester Mark 1 Online Emulator
Play Manchester Mark 1 using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Factorial series | Manchester Mark 1 | Manchester Mark 1 | open | Open ⛶ | |
| Squares via index register | Manchester Mark 1 | Manchester Mark 1 | open | Open ⛶ |
Chips
Notes
Embedding
The Manchester Mark 1 here is authored from scratch in one small file, mark1.js. It is a plain global — MARK1.create(canvas) returns a machine object whose whole state is ordinary JavaScript (40-bit store words and the 80-bit accumulator are BigInt), so the debugger reaches straight into it with no wasm heap or hidden loop. A tiny two-pass assembler, MARK1.assemble, turns a readable listing into the store map.
Boot. Create the machine on a <canvas>, assemble and load a program, then run your own loop built on mark1.step() (execute exactly one instruction):
var mk1 = MARK1.create(canvas);
var prog = MARK1.assemble([
{ label: 'loop', f: 'LDP', a: 'prod' }, // A := prod
{ f: 'MUL', a: 'kval' }, // A := A × k (hardware multiplier)
{ f: 'PRD' }, { f: 'NL' }, // teleprinter: print A, newline
/* … */
]);
mk1.load(prog);
(function loop(){
var r = mk1.step(); // 'ok' | 'stop'
mk1.render();
if (r !== 'stop') requestAnimationFrame(loop);
})();
The machine is plain fields. Everything the debugger needs is live on the object:
| Member | Kind | What it does |
|---|---|---|
mk1.step() | method | Execute exactly one instruction; returns 'ok' or 'stop' (halted by STP). The single-step primitive. |
mk1.a | field | The 80-bit accumulator (a BigInt), holding full 40×40 products from MUL. |
mk1.b | field | The eight B-lines (index registers); b[0] is hard-wired 0. |
mk1.ci | field | The control register (program counter), a store-line number. |
mk1.store | field | The 128 store lines (an array of 40-bit BigInt words). |
mk1.peek(a) · mk1.poke(a,v) | methods | Side-effect-free read / write of a store line (a 40-bit word fits exactly in a JS number). |
mk1.onWrite(a,v) | hook | Called on every store write; the boot uses it to implement watchpoints. |
Debugger integration
The plug-in manchester-mark-1-debug.js calls EmuKit.defineMachine against the live core published on window.EMU_BOOT. Because the whole machine is ordinary JavaScript, no wrapping is needed:
- Registers. The 80-bit accumulator is a
BigInt, but the shared register view edits 32 bits at a time, so it is exposed as two fieldsA-lo/A-hi(reconstructed on write-back). Alongside areCI,PI, the current tubePAGE, the seven index registersB1–B7, and theSTOPflag. Eachset()writes straight back into the core and re-renders. - Memory. One chip, the 128-line store, read side-effect-free through
peek. Thedisasmview runs the newmark1decoder;bitsshows the raw 40-bit dot pattern;hexshows bytes. - The decoder.
debugger/src/cpus/mark1.jsregisters decodermark1. It reads the true 40-bit word off the live machine (the shared views hand it a byte-masked reader) and splits the low 20 bits into function / B-line / address, printing e.g.MUL 20orLDP 34 B1. A line with any high bit set is data and prints as.line <value>. - Transport. The boot owns the run loop, so
pause/resume, single-instructionstep, executionbreakpoints(a host-sideSetof line numbers checked before eachstep()) and writewatchpoints(checked insideonWrite) all work with no change to the core.
Architecture
The Manchester Mark 1 ran at the University of Manchester in 1949, growing out of the SSEM "Baby" of 1948. It kept the Baby's Williams-Kilburn tube store and single accumulator but added the features that made it a working computer — several of them world firsts. This authored core reproduces those additions over the Baby:
- A wider 40-bit word (the Baby's was 32), held on the Williams-Kilburn tube in pages of 32 lines. This core has a 128-line store (four pages) shown one page at a time, backed by a magnetic drum that the drum-transfer instructions move a 32-line track at a time.
- Index registers — the "B-lines" (B-tube), a Mark 1 world first. A 3-bit B field in every instruction names a B-line whose contents are added to the address before the operand is fetched (B0 is hard-wired 0). This is what "modifying instructions" means and is why loops over tables became possible.
- An 80-bit double-length accumulator and a hardware multiplier (MUL) — the Baby could only subtract.
- Teleprinter I/O: characters are printed in the 5-bit Manchester teleprinter code (plus a decimal-print convenience so results are legible), onto the paper shown at the right.
An instruction is 20 bits: a 10-bit address S (bits 0–9), a 3-bit B-line (bits 10–12) and a 7-bit function (bits 13–19). The effective address is E = S + B[b].
| F | Mnemonic | Effect | vs. Baby |
|---|---|---|---|
| 0 | JMP | CI ← S[E] | as Baby |
| 1 | JRP | CI ← CI + S[E] | as Baby |
| 2 | LDN | A ← −S[E] | as Baby |
| 3 | LDP | A ← S[E] | new (direct load) |
| 4 | STO | S[E] ← A | as Baby |
| 5 | ADD | A ← A + S[E] | new (real addition) |
| 6 | SUB | A ← A − S[E] | as Baby |
| 7 | MUL | A ← A × S[E] | new (multiplier) |
| 8 | CMP | skip next line if A < 0 | as Baby |
| 9 | JEZ | skip next line if A = 0 | new |
| 10 / 11 / 12 | LDB / STB / IXB | B ← S[S] · S[S] ← B · B ← B + S[S] | new (index registers) |
| 13 / 14 | DRD / DWR | drum ↔ store page transfer | new (drum) |
| 15 / 16 / 17 | PRT / PRD / NL | teleprinter: char · decimal · newline | new (I/O) |
| 127 | STP | halt | as Baby |
The shared mark1 decoder turns each word back into these mnemonics in the disassembly, so you can watch the fetch-decode-execute cycle — and the multiplier and the index registers at work — one instruction at a time. (Authored simplification: the real Mark 1 packed two 20-bit instructions per 40-bit line; this core runs one per line so CI, breakpoints and the disassembly all address by line.)