SearchA-ZM › Manchester Mark 1

Manchester Mark 1

1949 Open source · Public domain Online

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.

Configurations

ConfigurationEmulatorMachineOSLegal
Factorial seriesManchester Mark 1Manchester Mark 1openOpen ⛶
Squares via index registerManchester Mark 1Manchester Mark 1openOpen ⛶

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:

MemberKindWhat it does
mk1.step()methodExecute exactly one instruction; returns 'ok' or 'stop' (halted by STP). The single-step primitive.
mk1.afieldThe 80-bit accumulator (a BigInt), holding full 40×40 products from MUL.
mk1.bfieldThe eight B-lines (index registers); b[0] is hard-wired 0.
mk1.cifieldThe control register (program counter), a store-line number.
mk1.storefieldThe 128 store lines (an array of 40-bit BigInt words).
mk1.peek(a) · mk1.poke(a,v)methodsSide-effect-free read / write of a store line (a 40-bit word fits exactly in a JS number).
mk1.onWrite(a,v)hookCalled 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 fields A-lo / A-hi (reconstructed on write-back). Alongside are CI, PI, the current tube PAGE, the seven index registers B1B7, and the STOP flag. Each set() writes straight back into the core and re-renders.
  • Memory. One chip, the 128-line store, read side-effect-free through peek. The disasm view runs the new mark1 decoder; bits shows the raw 40-bit dot pattern; hex shows bytes.
  • The decoder. debugger/src/cpus/mark1.js registers decoder mark1. 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 20 or LDP 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-instruction step, execution breakpoints (a host-side Set of line numbers checked before each step()) and write watchpoints (checked inside onWrite) 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].

FMnemonicEffectvs. Baby
0JMPCI ← S[E]as Baby
1JRPCI ← CI + S[E]as Baby
2LDNA ← −S[E]as Baby
3LDPA ← S[E]new (direct load)
4STOS[E] ← Aas Baby
5ADDA ← A + S[E]new (real addition)
6SUBA ← A − S[E]as Baby
7MULA ← A × S[E]new (multiplier)
8CMPskip next line if A < 0as Baby
9JEZskip next line if A = 0new
10 / 11 / 12LDB / STB / IXBB ← S[S] · S[S] ← B · B ← B + S[S]new (index registers)
13 / 14DRD / DWRdrum ↔ store page transfernew (drum)
15 / 16 / 17PRT / PRD / NLteleprinter: char · decimal · newlinenew (I/O)
127STPhaltas 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.)