EDSAC
The EDSAC, the Electronic Delay Storage Automatic Calculator, ran its first program on 6 May 1949 at the University of Cambridge Mathematical Laboratory, built by Maurice Wilkes and his team. It was one of the first practical stored-program computers and the machine on which David Wheeler invented the closed subroutine. This is an original implementation, written from scratch for emulators.org: a store of 17-bit words held in mercury delay lines and drawn on the monitor cathode-ray tube as a raster of dots, a 71-bit accumulator, a multiplier register and a sequence-control register. The order code is the Wilkes and Wheeler set of eighteen letters, A S H V N T U C R L E G I O F X Y Z, each with a short or long length bit.
It boots with the classic table of squares already running: the machine computes 1, 4, 9, 16 and on by summing successive odd numbers and stores each square into a growing table, so the binary numbers climb across the monitor tube while the teleprinter counts. The whole machine, accumulator, multiplier, sequence control and every store line, is exposed to the shared debugger, so you can single-step the fetch-decode-execute cycle, set breakpoints on an order line, watch a store line for writes, and read the program back as a disassembly. An on-screen console gives Start, Stop, Single EP, Reset and Clear; EDSAC itself read paper tape and was started from switches.
Runs on: Web browser
EDSAC Online Emulator
Play EDSAC using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Squares demo | EDSAC | EDSAC | open | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
The EDSAC here is authored from scratch in one small file, edsac.js. It is a plain global - EDSAC.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. Create the machine on a <canvas>, load a program (a map of store line → 17-bit order/number), then run your own loop built on edsac.step() (execute exactly one order):
var m = EDSAC.create(canvas);
m.load({0:20584, 1:114806, 2:20504 /* ... squares program ... */});
(function loop(){
var r = m.step(); // 'ok' | 'stop'
m.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 |
|---|---|---|
m.step() | method | Execute exactly one order (SC points at it); returns 'ok' or 'stop' (halted by the Z order). The single-step primitive. |
m.acc | field | The 71-bit accumulator, a signed BigInt; wide enough to hold a full double-length product. |
m.r · m.sc | fields | The multiplier register R and the sequence-control register SC (the program counter), read and written live. |
m.mem | field | The store, an array of 17-bit words; each word is at once a number and one order. |
m.peek(a) · m.poke(a,v) | methods | Side-effect-free read / write of a store line, used by the debugger's memory views. |
m.onWrite(a,v) | hook | Called on every store write; the boot uses it to implement watchpoints. |
Because the accumulator, R, SC and store are ordinary JavaScript, breakpoints are a host-side Set of order lines checked before each step(), and watchpoints are checked inside onWrite - no changes to the core.
Debugger integration
Wiring the EDSAC into the shared in-browser debugger needs only a boot shim and one new decoder, because the core was authored to expose its whole state.
1 · A controllable loop. The boot shim owns the run loop instead of letting the core free-run, so pause / resume / single-order-step work. When breakpoints are set, the loop checks m.sc against a Set before each order and stops on a match; a watched store write sets a flag inside m.onWrite that halts the loop on the next order boundary.
if (bps.size && bps.has(m.sc)) { running = false; break; } // execution breakpoint on SC
m.onWrite = function(a, v){ if (wps.has(a)) wpHit = true; }; // write watchpoint
2 · A new order-code decoder. The disassembly view needs to turn a 17-bit word back into an order, so a new decoder lives at /debugger/src/cpus/edsac.js. It splits the word into a 5-bit function code, a 10-bit address and the S/L length bit, maps the function code to its order letter (A S H V N T U C R L E G I O F X Y Z), and prints anything that is not one of the eighteen orders as .order:
var f = (w >>> 12) & 31, a = (w >>> 1) & 0x3ff, len = (w & 1) ? 'L' : 'S';
return { length: 1, mnem: FN[f], text: FN[f] + ' ' + a + ' ' + len };
Because the store word is 17 bits, the decoder reads the true word off window.EMU_BOOT.peek(addr) rather than the byte-masked reader the shared views hand it (which would truncate the word). Registers (A shown as a signed decimal, R, SC, and the STOP flag) are read and written straight off the live object each refresh, and the memory view reads through the side-effect-free peek.
Architecture
The EDSAC - Electronic Delay Storage Automatic Calculator - ran its first program on 6 May 1949 at the University of Cambridge Mathematical Laboratory, built by Maurice Wilkes and his team. It was one of the first practical stored-program computers and the machine on which David Wheeler invented the closed subroutine. Its store was a bank of mercury delay lines: acoustic pulses circulating down tubes of mercury, refreshed each cycle, with the contents of a line displayed on a small monitor CRT tube as a raster of dots - the display this emulator draws.
- Store of 17-bit short words (a long number is two adjacent words, 35 bits), each word at once a number and one order.
- Accumulator (A) - 71 bits, wide enough to hold a full double-length product from the multiplier.
- Multiplier register (R) - loaded by the H order, multiplied into A by V and N.
- Sequence control (SC) - the number of the next order.
An order is a 5-bit function letter, a 10-bit address and a short/long (S/L) length bit:
| Order | Effect |
|---|---|
A n · S n | add / subtract C(n) into the accumulator |
H n | copy C(n) into the multiplier register R |
V n · N n | A ← A ± R × C(n) |
T n · U n | store the accumulator into n (T then clears A, U does not) |
C n | collate - add the logical AND of R and C(n) into A |
R n · L n | shift the accumulator right / left |
E n · G n | jump to n if A ≥ 0 (E) or A < 0 (G) |
I n · O n · F n | read a tape row into n, print C(n), verify the last character |
X · Y · Z | no-op, round the accumulator, stop |
The default demo is the classic table of squares: it computes 1, 4, 9, 16 ... by summing successive odd numbers (1, 1+3, 1+3+5 ...) and stores each square into a growing table in the store, so the binary numbers climb across the monitor tube while the teleprinter counts. It advances the store address by modifying its own transfer order each pass - the self-modifying-code style that stored-program machines like the EDSAC made possible. The shared debugger's edsac decoder turns each word back into these mnemonics in the disassembly view, so you can watch the fetch-decode-execute cycle one order at a time.