Assembler (EDSAC)
The symbolic order code of the Cambridge EDSAC, loaded by David Wheeler's Initial Orders — widely described as the world's first assembler, and the system that introduced the subroutine library, the relocating loader and the programming textbook.
Created by Order code designed by Maurice Wilkes and the Cambridge University Mathematical Laboratory; the Initial Orders that turned it into a symbolic language were written by David Wheeler
EDSAC assembly language is where writing programs in letters instead of binary begins. The
Electronic Delay Storage Automatic Calculator ran its first fully automatic calculation at
the University of Cambridge Mathematical Laboratory on 6 May 1949, and from that first day
programs reached it not as bit patterns but as characters punched on five-hole paper tape —
A 15 F, T 64 K, E Z P F — which a small fixed program called the Initial Orders read
and converted into orders in the mercury delay-line store. That fixed program, written by
the research student David Wheeler, is routinely described as the world’s first assembler.
What makes EDSAC’s system remarkable is not merely that it existed first. Within a few months it also had relocation, a parameter mechanism for position-independent code, a convention for calling and returning from subroutines, a catalogued library of those subroutines on tape in a filing cabinet, and, by 1951, a textbook explaining the whole practice to outsiders. Almost every idea in that list is still in use.
The machine underneath
EDSAC’s store was a set of temperature-stabilised mercury delay lines. Accounts of its size differ in how they count: Martin Richards describes 512 words of 35 bits, each splittable into two 17-bit halves addressed separately, while the machine is more often described as having 512 short (17-bit) locations at the outset, a second battery of delay lines brought into service in 1952, and the full 1024 short locations reportedly not dependably available until 1955 or 1956. Two registers were visible to the programmer: a 71-bit accumulator and a 35-bit multiplier register. Numbers were signed binary fractions in the range -1 ≤ x < 1, with the binary point immediately below the sign bit, though integers were routinely worked with by scaling.
An order occupied 17 bits:
5 bits 1 bit 10 bits 1 bit
+---------+--------+-----------+-------+
| op code | unused | address | S/L |
+---------+--------+-----------+-------+
On tape, an order was simply the character whose five-bit code was the operation code,
followed by the address in decimal, followed by S or L (in the later notation, F or
D) to set the length bit. R16S assembled to 00100 0 0000010000 0; T11L to
00101 0 0000001011 1. There was no translation table to speak of — the mnemonic letter
and the opcode were the same five bits, which is exactly why the first Initial Orders could
fit in 31 words.
Speed, for context: the machine executed roughly 600 orders per second, read paper tape at 50 characters per second and printed at nearly seven characters per second on a Creed teleprinter. Those are the figures quoted for the original machine and its peripherals, not a benchmark against anything else; there was nothing to benchmark against.
The order code
| Order | Effect |
|---|---|
A n | Add the contents of n to the accumulator |
S n | Subtract the contents of n from the accumulator |
H n | Copy the contents of n into the multiplier register |
V n | Multiply, adding the product into the accumulator |
N n | Multiply, subtracting the product from the accumulator |
T n | Transfer the accumulator to n and clear it |
U n | Transfer the accumulator to n without clearing |
C n | Collate (logical AND) with the multiplier, adding into the accumulator |
R, L | Arithmetic shift right or left, the distance encoded by the least significant one bit of the address |
E n | Jump to n if the accumulator is ≥ 0 |
G n | Jump to n if the accumulator is < 0 |
I n | Read the next five-bit tape character into n |
O n | Print the character in the top five bits of n |
F n | Verify the last character output |
X | No operation |
Y | Round the accumulator (add one at bit 35) |
Z | Stop the machine and ring the bell |
There is no divide order and, in the machine as programmed here, no index registers —
indexing was invented elsewhere around 1950, and Wheeler is reported to have designed an
index register for EDSAC only in 1953, after a stay at the University of Illinois. Division
was a library subroutine, and walking through an array meant writing self-modifying code that added a constant to the
address field of an order held in store. The 1949 squares program modifies its own T
order in location 25 to advance the load address, and does something similar to cycle an
A order through a table of powers of ten.
There is also no “equals” test: E branches on non-negative and G on negative, so loops
were customarily written to count up to zero from a negative starting value.
Initial Orders 1: an assembler in 31 words
The first Initial Orders were placed in locations 0 to 30 by uniselectors — mechanical
read-only memory — when the machine was started, and execution began at location 0. The
loop is short enough to summarise: read a character and shift it into the top five bits of
a word to form the opcode; read decimal digits, accumulating value × 10 + digit by
multiplying against a constant 10 << 11 held in the multiplier register; read S or L
and derive the length bit from it; assemble the three parts and store the result with a
T n S order in location 25 whose own address field is incremented on every pass.
Several words do double duty. Location 2 contains T0S, which is both a working
instruction and the bit pattern 00101000000000000 used as a multiplier constant.
Locations 4 and 5 sit in the middle of the code and are jumped over because they hold the
constants 2 and 10. The first order on every program tape has to be a T n S whose address
marks the end of the program, because the loader compares it against the running store
pointer to decide when to stop loading and fall through into the program.
It worked, and it was a decisive improvement on toggling in binary. But every address was absolute. Inserting one order meant renumbering the destinations of every branch that crossed it, and a subroutine could only live at the address it was written for — which made a shared library nearly unmanageable.
Initial Orders 2: relocation, code letters, control combinations
Wilkes gave Wheeler the problem, and in September 1949 the new version went in. The budget was 42 orders; Wheeler used 41. Contemporaries called it “the leading example of programming virtuosity”, and the description is not really an exaggeration.
The new system added control combinations — what a modern assembler calls directives:
| Combination | Meaning |
|---|---|
T m K | Set the load point to m (the equivalent of ORG) |
G K | Set the θ parameter to the current load point |
T Z | Restore the previous θ parameter |
E m K P F | Enter the program at location m |
E Z P F | Enter the program at location θ |
P Z, P K | Start of a new tape block |
and code letters. The terminating letter of an order no longer just chose the operand
length; it named a store location whose contents were added to the order’s address as it
was loaded. There were fifteen code letters: F referred to a location holding zero, θ to
the origin of the current routine, D to one, and φ, H, N, M through V were left
free for the programmer. Writing A 5 θ therefore meant “add the contents of the location five words past the start
of this routine”, and the routine could be loaded anywhere.
That single mechanism is what made the subroutine library practical. A tape could be copied
onto the front of a program unchanged, preceded by a T m K and a G K that placed it,
and the routine’s internal references would fix themselves up at load time. The conventional
layout was to load from location 56 upwards, packing subroutines and the master routine
end to end with no gaps, working out the addresses from the lengths published in each
routine’s specification.
Here is a complete hello-world program in the notation of the period, taken from
Campbell-Kelly’s tutorial guide. It prints HI rather than Hello World because, as the
guide puts it, the longer message “would make the program rather longer than necessary”;
@ is how the simulator writes the θ code letter in plain ASCII:
T64K load from location 64
GK set θ to the load point
ZF 0: stop
O5@ 1: print letter shift
O6@ 2: print "H"
O7@ 3: print "I"
ZF 4: stop
*F 5: letter-shift character
HF 6: "H"
IF 7: "I"
EZPF enter at θ
Changing T64K to T56K moves the whole program. The leading stop order is deliberate:
programs were loaded on a tank boundary and halted so the operator could check on the
monitor tube that the tape had read in correctly before pressing Reset.
The Wheeler jump
EDSAC had no call instruction, so the return address had to be manufactured. The calling sequence became the standard idiom:
m A m F pick up this order itself into the accumulator
m+1 G n F jump to the subroutine at n
m+2 ... control returns here
n A 3 F form the return link from a constant kept in location 3
n+1 T p F plant it as the final order of the subroutine
...
p ( E m+2 F ) return link planted here
The trick is that A m F loads its own bit pattern, which the subroutine then arithmetically
converts into an E m+2 F jump and stores over its own last order. Wilkes, Wheeler and
Gill’s presentation of this — together with the discipline of closed subroutines that
could be called from anywhere and the catalogue that documented each one’s entry
conditions, length and running time — is the ancestor of the calling convention and the
library specification alike.
The textbook
The Preparation of Programs for an Electronic Digital Computer, published by Addison-Wesley in 1951 and universally known as Wilkes, Wheeler and Gill or WWG, grew out of a September 1950 laboratory report circulated to about a hundred people. It is the first book on programming. Beyond the order code and the Initial Orders it contains the first published account of a reusable code library with per-routine specifications, an early description of debugging by memory dump — the “post-mortem routine” — and a working argument, stated plainly in its own introduction, that programming should be an ordinary activity for scientists rather than “something of a magic art, closed except to a few specialists”. A second edition followed in 1957.
Why it matters
EDSAC’s order code is a small and awkward instruction set, and taken on its own it would be a footnote. What makes it foundational is everything Wheeler wrapped around it in 1949: the recognition that the human-readable form of a program and the loader that translates it are themselves software, that translation can do arithmetic on addresses, and that if it can do that then code becomes movable, and if code is movable it becomes shareable.
Every assembler since has been a bigger version of the same argument. The ORG directive,
the relocating linker, the object library, the calling convention, the documented API entry
and the idea that you look programs up in a catalogue instead of writing them again — all of
them are visible, in miniature, in 41 orders written by a Cambridge research student in
September 1949.
Trying it today
EDSAC has no Docker image and no compiler that targets it, but the language runs. Martin Campbell-Kelly’s simulator, maintained at Warwick and distributed through the EDSAC Replica Project, reproduces the machine’s front panel, both sets of Initial Orders, the original subroutine library and the original program documentation, and ships with a tutorial guide that includes the summer-school exercises. Andrew Herbert has published a small EDSAC assembler in Python — written for short test programs loaded through the replica’s signal sequence injector — and a command-line EDSAC emulator in C. And at The National Museum of Computing at Bletchley Park, volunteers are building a working replica intended to run the same tapes in mercury-delay-line hardware.
Timeline
Notable Uses & Legacy
The EDSAC subroutine library
The first catalogued library of reusable code. Routines were grouped by letter and serial number (P6, for example, prints a short positive integer; its published specification gives 32 storage locations and a running time of about 900 milliseconds per number on the original machine — a figure from the routine's own library entry, not a comparison against any other machine) and were copied from library tapes onto the program tape at punching time. Wilkes, Wheeler and Gill's 1951 book published the library along with specifications for each routine; the library eventually grew to nearly a hundred subroutines.
LEO I at J. Lyons & Co.
The Lyons Electronic Office was modelled closely on EDSAC and went into operation in 1951 running clerical and valuation jobs for the catering company — the first use of a stored-program computer for routine commercial work. Its debt to Cambridge was architectural and methodological alike: the order code, the delay-line store and the subroutine-library style of programming all came across.
Scientific computing at Cambridge
EDSAC ran as a service for the whole university rather than as a laboratory experiment. Wilkes and Wheeler used it in 1950 to integrate a differential equation on gene frequencies, reported as the first use of a computer for a problem in biology, and in 1951 J. C. P. Miller and Wheeler used it to find a 79-digit prime, then the largest known.
OXO
Sandy Douglas's noughts-and-crosses program, written in EDSAC orders around 1952 as part of doctoral work on human-computer interaction. The player entered moves on a telephone dial and the board was drawn on one of the machine's cathode-ray monitor tubes.
Teaching programming
Cambridge ran summer schools on EDSAC programming from 1950, and the exercises set there — along with the original subroutine library and program documentation — are still distributed with Martin Campbell-Kelly's EDSAC simulator, which reproduces the machine's controls and both sets of Initial Orders.
Simulation and reconstruction
The language is still executable. Campbell-Kelly's Warwick simulator runs original tapes under Initial Orders 1 or 2 on Windows, macOS and Linux; Andrew Herbert has published a small EDSAC assembler in Python (written for test programs loaded through the replica's signal sequence injector) and a command-line emulator in C; and the volunteer replica at The National Museum of Computing is being built to run the same order code in hardware.