The Birth of Software - Punch Cards to the First Compiler
15.0 What this chapter gives you#
- You will be able to say exactly what a program is at the lowest level, and show a real one as raw numbers.
- You will be able to take a handful of bytes and work out, by hand, what the machine will do with them.
- You will be able to describe how ENIAC was programmed in 1946 with cables and switches, and how long a change took.
- You will be able to explain a punched card completely: its size, its 80 columns, its 12 rows, and how a letter was stored as holes.
- You will be able to say what an assembler is and why a label beats a hand-counted address.
- You will be able to answer “who wrote the first compiler” honestly, and say why the honest answer has several parts.
- You will be able to say what Grace Hopper’s A-0 actually did in 1952, and what it did not do.
- You will be able to explain why FORTRAN had to be fast or it would have failed, and why COBOL still runs banks in 2026.
- You will be able to tell the moth story correctly, including the part most retellings get wrong.
- You will be able to trace the line from a human carrying card decks to a modern operating system, and from Multics to UNIX to C.
15.1 What a program is at the bottom#
PLAIN15.1.1 in simple words#
- A computer’s memory is a very long row of numbered boxes.
- Each box holds one small number, from 0 to 255. That is one byte.
- A program is a run of boxes that the processor has agreed to read as orders instead of as data.
- The processor keeps a marker pointing at one box. It reads the number there, does what that number means, and moves the marker on.
- That is the whole show. Read a number, do the thing, move on. Forever.
- The same number can be an order in one place and data in another. Only position and agreement decide which.
- Writing a program in 1948 meant choosing every one of those numbers yourself, by hand, and getting every one right.
PLAIN15.1.2 a picture in your head#
- Think of a long street of numbered houses, and one postman.
- Each house has one card in the letterbox with a number on it.
- He carries a notebook with a few slots. Those are the processor’s registers, its scratch space.
- He never wonders whether a card is an order or a note. Where he is standing decides that. Walk him into a shopping list and he will obey the shopping list.
Where this comparison breaks: a real processor does not work in one tidy line. Modern chips fetch many instructions ahead, guess which way branches go, and run several at once, then hide the mess so it looks sequential.
PLAIN15.1.3 a worked example#
- Here is a real program for the MOS 6502, the chip in the Apple II, the Commodore 64 and the Nintendo Entertainment System.
- In memory it is nothing but these seven numbers.
Address Bytes What the processor does
0600 A9 05 put 5 into the accumulator
0602 69 03 add 3 to the accumulator
0604 8D 00 02 write accumulator into address 0200
0607 00 stop
- At 0600 the byte is A9, meaning “load the accumulator with the next byte”. The next byte is 05, so the accumulator becomes 5.
- At 0602 the byte is 69, meaning “add the next byte”. That is 03, so the accumulator becomes 8.
- At 0604 the byte is 8D, meaning “store the accumulator at the two-byte address that follows”. Those bytes are 00 then 02.
- The 6502 stores addresses low byte first, so 00 02 means address 0200, not
- That ordering is called little-endian.
- Address 0200 now holds 8. At 0607 the byte 00 is BRK, and the machine stops.
- That is a complete program. Seven numbers. Nothing else exists.
PLAIN15.1.4 what is really happening inside#
- Inside the processor is a register called the program counter, holding the address of the next instruction.
- That address goes onto the address wires, and memory puts the byte at that address onto the data wires.
- The byte lands in the instruction register, and a block of logic called the decoder turns on a specific set of control wires.
- Meanwhile the program counter has already advanced to the next byte.
- A9 does not “mean” load in any deep sense. The decoder was built so the bit pattern 1010 1001 turns on the load-immediate wires. That is all.
- Different chip, different wiring, different meanings for the same numbers. That is why code for one processor family is noise to another.
TECHNICAL15.1.5 the engineer’s version#
- The 6502 is an 8-bit processor with a 16-bit address bus, so it addresses 65,536 bytes. MOS Technology introduced it in September 1975 at 25 United States dollars, against roughly 179 dollars for competing parts.
- User-visible registers: A (accumulator), X and Y (index), SP (stack pointer, fixed to page 01), PC (16 bits) and P (status flags).
- A9 is LDA immediate, 2 bytes, 2 cycles. 69 is ADC immediate, 2 bytes, 2 cycles. 8D is STA absolute, 3 bytes, 4 cycles. 00 is BRK, 1 byte, 7 cycles.
- ADC adds the carry flag as well as the operand. That is not optional. If carry is set from earlier work, the example above yields 9, not 8. Correct 6502 code clears carry first with CLC, opcode 18.
- Little-endian ordering for 16-bit operands is an architectural rule of the 6502, not a convention you may vary.
| Item | 6502 (1975) | x86-64 (today) |
|---|---|---|
| Opcode length | 1 byte | 1 to 4 bytes |
| Instruction length | 1 to 3 bytes | 1 to 15 bytes |
| Address bus | 16 bits | 48 bits used |
| Documented opcodes | 151 | over 1,000 |
- To see this today:
objdump -don Linux,otool -tvon macOS,xxdorhexdump -Cfor raw bytes, andgdbwithx/8xbto dump memory.
The honest version: “the CPU reads a byte and does it” is a fair description of a 1975 chip and a poor one of a 2026 chip. A modern x86 core decodes variable-length instructions into fixed micro-operations, renames registers, reorders execution, and retires results in order to keep up the appearance of sequence. The programmer’s model is still one at a time; the hardware stopped working that way around 1995.
WORDS15.1.6 remember these#
- Byte — a number from 0 to 255 — 8 bits, the standard addressable unit.
- Machine code — the raw numbers a chip obeys — the binary encoding of an instruction set architecture.
- Opcode — the number saying which operation — the operation field of an encoded instruction.
- Program counter — the marker for the next order — a register holding the address of the next instruction to fetch.
- Register — the processor’s scratch slots — small fast storage inside the core, named in the instruction encoding.
- Little-endian — low part of a number stored first — least significant byte at the lowest address.
15.2 Before any language existed: programming by rewiring#
PLAIN15.2.1 in simple words#
- In 1945 there was no such thing as a programming language, and barely such a thing as a program.
- ENIAC, finished in late 1945 at the University of Pennsylvania, did not read instructions from memory. It had no memory for instructions.
- To make it do a calculation you physically rebuilt the connections between its parts.
- You plugged heavy cables between panels, exactly like an old telephone switchboard, and set banks of rotary switches by hand.
- The program existed as the arrangement of cables and the positions of switches. Nothing was stored anywhere.
- A new problem took weeks of planning on paper, days of physical work on the machine, and days more of finding what was wired wrong.
- The people doing this were not called programmers. They were called operators, because until then “computer” meant a person who computed.
PLAIN15.2.2 a picture in your head#
- Think of a model railway with no track laid down.
- To run a train from the station to the mine you lay every piece of track, set every point and connect every signal wire yourself.
- Now you want the train to go to the quarry instead. There is no button for that. You lift the track and lay it again.
- The layout is the program. A stored-program computer is the opposite: the track is fixed forever, and you hand the driver a route on a slip of paper.
Where this comparison breaks: ENIAC’s units could repeat and could branch on a condition, so it was more capable than fixed track. And in 1948 it was converted so its function tables held a stored program, cutting setup from days to hours at the cost of running about six times slower.
PLAIN15.2.3 a worked example#
- ENIAC had 20 accumulators, each holding a 10-digit decimal number.
- To compute “add accumulator 3 and accumulator 5 into accumulator 7” you did the following.
- Run a program cable from a digit output socket on accumulator 3 to a digit input socket on accumulator 7.
- Run a program pulse cable so the right control pulse triggers both transmissions at the same moment in time.
- Do that for every step of the calculation. There were hundreds of steps.
- Then test it, and when the answer is wrong, work out whether the fault is your wiring, a bad switch, or one of 18,000 vacuum tubes that has failed since breakfast.
PLAIN15.2.4 what is really happening inside#
- ENIAC was a set of separate calculating units that could be joined in any pattern.
- Two kinds of cable ran between them. Digit trunks carried the numbers. Program trunks carried timing pulses meaning “now”.
- So a program was a graph: which unit sends numbers to which, and in what order the “now” pulses fire. That is closer to circuit design than to writing instructions.
- The three function tables were racks of switches, 1,200 ten-way switches per table, set by hand to hold constants and lookup values.
- Because the units ran in parallel, ENIAC could do several things at once. It was a parallel machine before it was a programmable one.
- In 1948 it was rewired once, permanently, so the function tables held a list of coded orders that the machine fetched and obeyed.
- That change turned a rewiring job into a switch-setting job, and it is the moment ENIAC became something we would recognize as programmable.
TECHNICAL15.2.5 the engineer’s version#
- ENIAC: Electronic Numerical Integrator and Computer, built at the Moore School of Electrical Engineering, University of Pennsylvania, for the US Army Ballistic Research Laboratory.
- First serious work: December 1945, Los Alamos thermonuclear calculations. Publicly announced and dedicated 14 to 15 February 1946.
- About 18,000 vacuum tubes, 7,200 crystal diodes, 1,500 relays, over 30 short tons, roughly 30 by 3 metres of floor space, 150 kilowatts.
- Clock rate 100 kHz, giving a 200-microsecond addition cycle: around 5,000 additions per second.
- The six principal programmers were Kathleen McNulty, Jean Jennings, Betty Snyder, Marlyn Wescoff, Frances Bilas and Ruth Lichterman. They were hired as human computers and taught themselves the machine from wiring diagrams.
- The 1948 converter-code modification, with input from John von Neumann and implemented with Richard Clippinger and Adele Goldstine, gave ENIAC a 60-order instruction set read from function table switches.
| Task | ENIAC 1946 | ENIAC after 1948 |
|---|---|---|
| Set up a new program | days | hours |
| Fix a coding mistake | hours | minutes |
| Additions per second | about 5,000 | about 800 |
The honest version: the popular line “ENIAC took two weeks to reprogram” compresses several different things. Planning could take weeks, physical setup days, and debugging days more. The 1948 conversion is the line that matters, and after it ENIAC was slower but far more usable.
WORDS15.2.6 remember these#
- Plugboard — a panel you wire by hand — a patch panel defining data and control routing.
- Accumulator — a box holding a running total — a register that is both operand source and result destination.
- Function table — a rack of setting switches — read-only storage for constants, later used as instruction memory.
- Stored program — orders kept in memory like data — the von Neumann model, with instructions and data in one addressable store.
- Setup time — the wait before the machine can start — non-productive time between jobs, the cost batch systems later attacked.
15.3 Programming in raw numbers: switches, tape and cards#
PLAIN15.3.1 in simple words#
- Once machines stored their programs in memory, the question became how to get the numbers in there.
- The first answer was the crudest possible: a row of switches on the front of the machine, one switch per bit.
- The second answer was paper tape: a ribbon of paper with rows of holes punched across it. A hole is a 1, no hole is a 0.
- The third answer, which ruled computing for forty years, was the punched card: a stiff paper rectangle holding one line of up to 80 characters.
- A program was a stack of cards, called a deck, held with a rubber band.
- You gave your deck to an operator. Hours or days later you got a printout back. One mistake meant fixing one card and queueing again.
PLAIN15.3.2 a picture in your head#
- Imagine writing an essay where each line goes on its own index card, and you may not see the essay until a stranger reads all the cards aloud.
- The cards must be in perfect order, there are 2,000 of them, and they are not fastened together.
- So you draw a diagonal ink line across the top edge of the whole stack. If a card moves, the line has a jog in it.
- You punch a fresh card 412, slide it in, and go back to the shelf. One full day for one typing mistake.
Where this comparison breaks: index cards can be read by anyone. A punched card carried its content as holes, and the characters printed along the top edge were an optional courtesy from the keypunch. Without that printing, a card was unreadable by a human.
PLAIN15.3.3 a worked example#
- Here is exactly how characters were stored as holes. The coding is called Hollerith code, after Herman Hollerith, who patented punched-card tabulating in 1889 for the 1890 United States census.
- A card has 12 rows. From the top edge down they are row 12, row 11, row 0, then rows 1 to 9.
- Rows 12, 11 and 0 are the zone rows. Rows 0 to 9 are the digit rows. Row 0 does double duty.
- A digit is a single punch in its own row. A letter is two punches: one zone plus one digit.
- A to I are zone 12 with digits 1 to 9. J to R are zone 11 with digits 1 to
- S to Z are zone 0 with digits 2 to 9.
- Notice S starts at digit 2, not 1. There are 26 letters and 27 slots, so the last group is short by one. That quirk is real.
row 'A' 'J' 'S' '5'
12 -> X . . .
11 -> . X . .
0 -> . . X .
1 -> X X . .
2 -> . . X .
3 -> . . . .
4 -> . . . .
5 -> . . . X
6 -> . . . .
7 -> . . . .
8 -> . . . .
9 -> . . . .
- So A is holes in rows 12 and 1 of one column, S is holes in rows 0 and 2, and the digit 5 is one hole in row 5.
- Eighty columns gives eighty characters per card, and that is where the traditional 80-character terminal width comes from.
PLAIN15.3.4 what is really happening inside#
- A keypunch is a typewriter that makes holes instead of ink. It also prints the characters along the top edge, which is called interpreting.
- A card reader pulls cards through one at a time and shines light or presses metal brushes at each of the 960 hole positions.
- Where there is a hole, light passes or a brush completes a circuit. That is one bit.
- So a card is not read as characters. It is read as 12 bits per column, and software decides what those 12 bits mean.
- Your deck joined a queue with everyone else’s, and the machine ran jobs one after another with no human in between. That is batch processing.
- Turnaround, from handing in your deck to collecting your printout, was a few hours in a well-run university and overnight or worse elsewhere.
- Because turnaround was slow, programmers did something we have nearly lost. They checked their code line by line on paper first, called desk checking.
write code on a coding sheet (30 minutes)
|
v
keypunch each line onto a card (1 hour)
|
v
hand the deck in at the window (join the queue)
|
v
operator loads it, machine runs it (2 seconds of CPU)
|
v
printout goes into a pigeonhole
|
v
you collect it next morning (turnaround: 20 hours)
|
v
one missing comma -> do it all again
TECHNICAL15.3.5 the engineer’s version#
- The IBM 80-column card, introduced in 1928, measures 7 and 3/8 by 3 and 1/4 inches, that is 187 by 83 millimetres, on stock about 0.007 inches or 180 micrometres thick. Roughly 143 cards stack to one inch.
- Rectangular holes replaced earlier round holes precisely so columns could be packed tighter, doubling capacity from 45 to 80 columns.
- Columns 73 to 80 were reserved by convention for a card sequence number. That is why FORTRAN, by rule, ignores columns 73 to 80 of every line.
- A dropped deck was recoverable if and only if you had punched those sequence numbers, by running it through a card sorter such as the IBM 82, 83 or 84.
| Device | Role | Speed |
|---|---|---|
| IBM 026 keypunch | punch cards by hand | typing speed |
| IBM 711 (for 704) | card reader | 250 cards/min |
| IBM 1402 | card reader/punch | 800 read, 250 punch |
| IBM 2540 | card reader/punch | 1,000 read, 300 punch |
- Front-panel switch entry survived into the microcomputer era. The Altair 8800 of January 1975 shipped with no keyboard: you entered the bootstrap loader on toggle switches, one byte at a time.
- Job control was itself punched on cards. IBM’s Job Control Language, JCL, survives, and its statements still begin with two slashes in columns 1 and 2 because that is where a card reader saw them.
The honest version: “turnaround was a day” is a rough average that varied enormously. A physics group with its own machine at 3 a.m. might get five runs an hour; a student at a busy service bureau might get one run a day, and in bad commercial cases two or three days.
WORDS15.3.6 remember these#
- Punched card — stiff card storing data as holes — 80-column, 12-row IBM card using Hollerith encoding.
- Deck — a stack of cards making one program — an ordered card file, sequence-numbered in columns 73 to 80.
- Keypunch — the machine that punches cards — a card punch with a keyboard, for example the IBM 026 or 029.
- Batch processing — jobs run one after another with no user present — non-interactive execution under a resident monitor.
- Turnaround — how long you wait for your answer — elapsed time from job submission to output delivery.
- Desk checking — reading your own code before running it — manual static verification, the ancestor of code review.
15.4 The first step up: mnemonics and assembly language#
PLAIN15.4.1 in simple words#
- Writing programs as numbers works, and it is unbearable.
- You must remember that 169 means load and 141 means store, for hundreds of operations, with no help.
- The fix is small and it changed everything: let people write short words instead of numbers, and let a program do the translation.
- Instead of A9 you write LDA. Instead of 8D you write STA. These short words are mnemonics, which just means memory aids.
- Instead of “jump back 10 bytes” you write “jump to loop”, and put the word
loopbeside the line you meant. That word is a label. - The program that turns this text into numbers is an assembler.
- An assembler is not clever. Mostly it is one line in, one instruction out. But it removes the two things humans are worst at: remembering arbitrary numbers, and counting.
- This is the first time in history that a program’s job was to write another program.
PLAIN15.4.2 a picture in your head#
- Imagine giving directions using only distances: go 412 metres, turn, go 78 metres, turn, go 1,050 metres.
- Now someone adds a roundabout early in the route. Every distance after it is wrong and must be recomputed.
- Labels are street names: go to Mill Street, turn towards the bridge. Add a roundabout and the directions still work, because names do not shift when things move.
- The assembler is the local who converts street names back into exact distances, correctly, in a second.
Where this comparison breaks: an assembler does not choose a route. It has no freedom at all. Every line you write becomes the instruction you asked for. A compiler, later in this chapter, does choose.
PLAIN15.4.3 a worked example#
- Here is a real 6502 program that adds the numbers 1 to 5. On the left is what the assembler produces; on the right is what you write.
Addr Bytes Label Assembly Comment
0600 A9 00 LDA #$00 running total = 0
0602 A2 01 LDX #$01 counter = 1
0604 18 loop: CLC clear the carry flag
0605 86 10 STX $10 put counter in memory $10
0607 65 10 ADC $10 total = total + counter
0609 E8 INX counter = counter + 1
060A E0 06 CPX #$06 is counter now 6?
060C D0 F6 BNE loop if not, go round again
060E 8D 00 02 STA $0200 save the total
0611 00 BRK stop
- Trace it. Total starts at 0, counter at 1.
- Pass 1: total = 0 + 1 = 1, counter becomes 2.
- Pass 3: total = 3 + 3 = 6, counter becomes 4.
- Pass 5: total = 10 + 5 = 15, counter becomes 6, the compare matches, and the branch is not taken. Address 0200 ends up holding 15.
- Now look at the byte F6 on the BNE line. That is minus 10 in two’s complement: jump back 10 bytes from the instruction after the branch.
- Here is the whole point. Insert one extra instruction anywhere between
loop:and the branch, and F6 becomes wrong. - With a label you insert the line and reassemble. The assembler recounts, and you never see the number F6 at all.
PLAIN15.4.4 what is really happening inside#
- An assembler reads your text twice, which is why they are called two-pass assemblers.
- On the first pass it walks the lines, keeps a running address counter, and writes down where every label lands. That list is the symbol table.
- It has to walk first because of forward references: you can jump to a label that appears later, and on first sight its address is unknown.
- On the second pass it converts each line to bytes, looking up every label in the symbol table.
- For a relative branch it does one more step: subtract the address of the next instruction from the target, and check the answer fits in a signed byte.
- And they handle macros: define a named block of lines once, then write its name wherever you want the block expanded.
TECHNICAL15.4.5 the engineer’s version#
- The earliest known symbolic coding scheme is in Kathleen Booth and Andrew Donald Booth’s 1947 work “Coding for A.R.C.” at Birkbeck College, London. Kathleen Booth is widely credited with inventing assembly language.
- EDSAC at Cambridge first ran a program on 6 May 1949. Its Initial Orders, written by David Wheeler, were a bootstrap routine held permanently in uniselector switches.
- Those Initial Orders read instructions as a single letter mnemonic, a decimal address and a length code, and turned them into binary on load. The IEEE Computer Society credits Wheeler as creator of the first assembler.
- Wheeler also devised the Wheeler Jump: place the return address in the accumulator, jump to the subroutine, and let the subroutine plant that address into its own final jump. That is the first practical closed subroutine call.
- EDSAC’s subroutine library reached 87 routines by 1951, covering floating-point arithmetic, trigonometry, differential equations and matrix work. That is the first software library.
- Maurice Wilkes, David Wheeler and Stanley Gill published “The Preparation of Programs for an Electronic Digital Computer” in 1951, the first programming textbook. It introduced the word “assemble” for joining separately written sections into one program.
- SOAP, the Symbolic Optimal Assembly Program, written by Stan Poley for the IBM 650 in 1955, placed instructions around the rotating drum so the next one arrived under the read head just as it was needed. That is optimization by an assembler.
| Year | Milestone | Who and where |
|---|---|---|
| 1947 | Coding for A.R.C. | K. and A. Booth, Birkbeck |
| 1949 | EDSAC Initial Orders | D. Wheeler, Cambridge |
| 1951 | First programming book | Wilkes, Wheeler, Gill |
| 1955 | SOAP for IBM 650 | Stan Poley, IBM |
- Modern equivalents to observe:
as(GNU assembler),nasm,objdump -dto disassemble, andgcc -Sto see the assembly a compiler emits.
The honest version: “assembly is one-to-one with machine code” is nearly true and not exactly true. Pseudo-instructions, macros and assembler-chosen branch widths mean one written line can become several instructions, or none. On MIPS and RISC-V this is routine and documented.
WORDS15.4.6 remember these#
- Mnemonic — a short word for an operation — the textual name of an opcode.
- Label — a name for a place in the program — a symbol bound to an address by the assembler.
- Assembler — the program turning mnemonics into numbers — a translator with a largely one-to-one instruction mapping.
- Symbol table — the list of names and addresses — the assembler’s map from identifiers to values, built in pass one.
- Subroutine — code you can call from many places — a closed routine entered with a return linkage.
- Macro — a named block that gets pasted in — textual expansion performed before assembly.
15.5 Why a higher language was needed#
PLAIN15.5.1 in simple words#
- Assembly made programming possible for ordinary mortals. It did not make it quick, and it did not make it safe.
- Problem one: assembly is welded to one machine. Code for an IBM 704 is worthless on a UNIVAC I. Buy a new computer, rewrite everything.
- Problem two: it is slow to write. One line is one machine operation, so a page of algebra becomes hundreds of lines.
- Problem three: it hides your intent. Reading it tells you what the machine does, never what you meant.
- So people asked the obvious question. Could you write the formula the way a mathematician writes it, and have a program produce the assembly?
- Many experienced programmers said no, and they were not being silly. Machines were tiny, machine time cost more than people, and a program that wasted 30 per cent of the machine was unacceptable.
- So the real question was never “can a machine translate”. It was “can a machine translate well enough that we do not lose the machine”.
PLAIN15.5.2 a picture in your head#
- Imagine a workshop where every screw is filed by hand by a master, and the masters are proud of it.
- Someone brings in a screw-cutting machine. The masters are not afraid of losing their jobs. They are afraid the screws will be worse.
- If the machine’s screws are 30 per cent weaker, the objection is correct and the machine should be rejected.
- If they are as good and made in a tenth of the time, the argument ends overnight and nobody files screws again. That is exactly what happened with compilers between 1952 and 1957.
Where this comparison breaks: code quality has many dimensions. A compiler can be worse on speed and far better on correctness, portability and maintenance, and for most work those matter more. The 1950s programmer with 4,096 words of memory did not have that luxury.
PLAIN15.5.3 a worked example#
- Take one line of mathematics: the roots of a quadratic need
d = b*b - 4*a*c. - In a high-level language that is one line and you can see the formula. In 1950s assembly it is roughly this shape of work.
load b get b into the accumulator
multiply b now accumulator holds b*b
store temp1 park it
load four get the constant 4
multiply a now 4*a
multiply c now 4*a*c
store temp2 park it
load temp1 get b*b back
subtract temp2 b*b - 4*a*c
store d save the answer
- Ten lines, two temporary locations you invented and must not reuse by accident, and one constant you placed in memory by hand.
- Nothing in the assembly says “this is the discriminant of a quadratic”. You must comment it, and comments drift out of date.
PLAIN15.5.4 what is really happening inside#
- The gap a compiler must cross is bigger than it looks. Four problems hide inside “translate the formula”.
- Parsing: work out from flat text that in
a + b * cthe multiplication binds tighter, so it happens first. - Temporaries: the machine has a handful of registers and your expression has many intermediate values. Something must decide what lives where.
- Addressing:
X(I)in a loop means a different memory address every time round, so the compiler must generate address arithmetic you never wrote. - Optimization: a naive translation reloads the same value from memory again and again. A human would not, and the compiler must not either.
- The fourth is the hard one, and it decided whether high-level languages would be accepted at all.
- A compiler producing code twice as slow as hand assembly would have been a curiosity. One that came within a few per cent would end the argument.
TECHNICAL15.5.5 the engineer’s version#
- The economics are the whole story. In 1957 an IBM 704 rented for roughly several tens of thousands of United States dollars per month, while a programmer earned a few hundred dollars per month. Machine time dominated.
- John Backus, who led the FORTRAN project, described the prevailing view plainly: most programmers of the time believed no automatic system could produce object code comparable to a good hand coder’s.
- The FORTRAN team’s target was output within roughly a factor of one to two of hand-written assembly for typical scientific code. They largely achieved it, and that is why FORTRAN spread.
- Earlier interpreted “automatic programming” systems, such as Backus’s own Speedcoding for the IBM 701 in 1953, ran perhaps 10 to 20 times slower than hand code. Useful, but easy to dismiss.
| Concern | Assembly | High-level language |
|---|---|---|
| Tied to one machine | yes | mostly no |
| Lines per formula | 10 to 30 | 1 |
| Type checking | almost none | some to strong |
| 1957 speed penalty | zero | a few per cent to 2x |
The honest version: the sceptics were not simply wrong and later proved foolish. For a decade they were right about specific cases, and even in 2026 there are hot loops in codecs, cryptography and kernels where hand-written assembly still beats a compiler. What changed is that those cases went from “most code” to a fraction of one per cent of it.
WORDS15.5.6 remember these#
- Portability — code that runs on more than one machine — source-level independence from a specific instruction set.
- Parsing — working out the structure of written text — building a syntax tree from tokens according to a grammar.
- Optimization — making generated code faster or smaller — semantics preserving transformation of an intermediate representation.
- Object code — the machine code a translator produces — a relocatable module containing code, data and relocation entries.
- Intermediate value — a part-finished result — a temporary held in a register or spilled to a stack slot.
15.6 Grace Hopper and the first compilers#
PLAIN15.6.1 in simple words#
- Grace Hopper joined the United States Navy Reserve in 1943 and in 1944 was assigned to the Harvard Mark I under Howard Aiken.
- The Mark I was an electromechanical calculator over 15 metres long. Hopper was one of its first programmers and wrote its manual, published in 1946 and running to over 500 pages.
- In 1949 she moved to the Eckert-Mauchly Computer Corporation to work on UNIVAC I, the first commercial computer sold in the United States.
- There she noticed something dull and important. Programmers kept copying the same routines out of notebooks by hand, and kept making copying errors.
- Her idea: keep those routines on magnetic tape, and let a program fetch them and stitch them together.
- She called that program a compiler, using the ordinary English meaning. To compile means to gather things from sources into one collection, as one compiles an anthology of poems.
- The system was called A-0 and it worked in 1951 and 1952.
- Here is the careful part. A-0 did not translate formulas into machine code. It gathered, positioned and joined ready-made routines.
- By today’s meanings, A-0 is much closer to what we now call a linker or loader than to a compiler.
- That is not a criticism. The word changed meaning afterwards, partly because of her, and we are judging 1952 by a 2026 dictionary.
PLAIN15.6.2 a picture in your head#
- Picture a cookbook where each recipe is on its own card in a filing drawer.
- You want a three-course dinner, so you write a short list: recipe 47, recipe 12 for 4 servings, recipe 90.
- An assistant takes the list, pulls those cards, rewrites the quantities for the servings you asked, and staples them into one set of instructions.
- That is A-0. The assistant invented no cooking. The assistant gathered, adjusted and joined.
- A modern compiler is a different assistant. You say “a light fish dinner for four” and it writes the recipes itself.
Where this comparison breaks: A-0 did more than staple. It adjusted the addresses inside each routine so they worked at their new position in memory, and substituted the arguments you supplied. That address adjustment is called relocation, and it is real work, not clerical work.
PLAIN15.6.3 a worked example#
- In A-0 you wrote a program as a list of call numbers with arguments, not as machine instructions. The shape of it was like this, in spirit.
your input what A-0 did with it
------------------------ ------------------------------
subroutine 015, X, Y find routine 015 on the tape
copy it into place
fix its internal addresses
plug in X and Y
subroutine 032, Y same again for routine 032
subroutine 007, Y, Z same again for routine 007
------------------------ ------------------------------
result: one runnable program on tape, ready to load
- Notice what is present: a library, selection from it, relocation, argument substitution, and output of a single runnable program.
- Notice what is absent: no arithmetic expressions, no variables in the modern sense, no control statements, no code generation from a grammar.
- Hopper described the work in a 1952 paper to the Association for Computing Machinery titled “The Education of a Computer”.
- A-2 followed in 1953. Remington Rand UNIVAC shipped it to customers by the end of that year with the source code included, and invited customers to send improvements back. That is an early ancestor of open source practice.
- Then came ARITH-MATIC (A-3), MATH-MATIC (AT-3), and the important one, B-0, better known as FLOW-MATIC.
PLAIN15.6.4 what is really happening inside#
- FLOW-MATIC, worked on from 1955 and substantially complete by 1959, is where Hopper’s real revolution sits.
- Her observation was about people, not machines. Business managers threw out anything full of mathematical symbols.
- So FLOW-MATIC used English words as its statements. It was the first programming language to do so.
- Statements looked like
COMPARE PRODUCT-NO (A) WITH PRODUCT-NO (B)andTRANSFER A TO DandREAD-ITEM A ; IF END OF DATA GO TO OPERATION 14. - Her management initially thought English-language programming impractical. She proposed it in 1953, and the compiler became publicly available in early
- It fed almost directly into COBOL.
TECHNICAL15.6.5 the engineer’s version#
- Now the credit question, precisely, because it is asked constantly and answered badly. There are at least four serious claims, and they answer different questions.
| Claim | Year | What it was |
|---|---|---|
| Corrado Bohm, thesis | 1951 | translator described on paper |
| Hopper, A-0 | 1952 | library linker and loader |
| Glennie, Autocode | 1952 | real translator, ran on Mark 1 |
| Backus et al, FORTRAN | 1957 | first widely used compiler |
- Corrado Bohm, doctoral thesis at ETH Zurich, submitted 1951, defined a language and described a translator for it written in that same language. It is arguably the first self-describing compiler. It was not implemented on a machine at the time.
- Grace Hopper, A-0, 1951 to 1952 on UNIVAC I. She coined and popularized the term “compiler”. The system selected subroutines from a tape library by call number, relocated them, substituted arguments and produced a single runnable program.
- In modern terminology, A-0 is a linking loader.
- Alick Glennie, Autocode, 1952, for the Manchester Mark 1 at the Royal Armament Research Establishment. It accepted a symbolic, algebra-like notation and generated machine code, and many historians call it the first compiler in the modern sense.
- Glennie’s own manual claimed the efficiency loss was no more than 10 per cent. It was barely used, even at Manchester.
- J. Halcombe Laning and Neal Zierler, MIT Whirlwind, from 1952 and operational by 1954. It accepted algebraic formulas in near-mathematical notation and produced machine code, with subroutine linkage, arrays and indexing, and a Runge-Kutta differential equation solver.
- It is often called the first operating algebraic compiler.
- R. A. Brooker’s Mark 1 Autocode, planned 1954 and working 1955, was the Manchester system actually used heavily, unlike Glennie’s.
- So the correct answers, depending on the question asked:
- First thing called a compiler: Hopper’s A-0, 1952.
- First compiler described in the modern sense: Bohm’s 1951 thesis, on paper only.
- First running translator from a higher notation to machine code: Glennie’s Autocode, 1952.
- First algebraic compiler in practical use: Laning and Zierler, 1954.
- First compiler that displaced hand assembly at scale: FORTRAN, 1957.
- Where experts disagree: some historians, including commentary published by the Association for Computing Machinery, argue plainly that A-0 was not a compiler and the popular claim overstates it.
- Others argue that in 1952 the word meant what Hopper made it mean, and that judging her by a later definition is unfair. Both positions are defensible.
- What is not in dispute, and is enough on its own: Hopper coined the vocabulary of automatic programming, built the first practical subroutine library system, led FLOW-MATIC, the first English-language programming language, and shaped COBOL.
- She reached the rank of Rear Admiral, retired in 1986, and died on 1 January 1992.
The honest version: “Grace Hopper wrote the first compiler” is defensible only if you use her 1952 definition of the word and not yours. The accurate sentence is that she wrote the first system anyone called a compiler, and it did linking and loading rather than translation. The exaggeration is unnecessary. Her uncontested achievements are larger than the disputed one.
WORDS15.6.6 remember these#
- Compiler — a program that turns your writing into machine code — a translator from a source language to machine or object code.
- Linker — the tool joining separate pieces into one program — resolves external symbol references between object modules.
- Loader — the tool putting a program into memory to run — performs relocation and transfers control to the entry point.
- Relocation — fixing addresses when code moves — adjusting address fields for a load-time base other than the assembled one.
- Subroutine library — a stored collection of reusable routines — an archive of object modules selected by name at link time.
- FLOW-MATIC — the first English-worded language — B-0, Remington Rand, 1955 to 1959, direct ancestor of COBOL.
15.7 FORTRAN: the compiler that had to be fast#
PLAIN15.7.1 in simple words#
- In late 1953 John Backus, aged 29 and working at IBM, sent his managers a proposal to let scientists write formulas instead of assembly.
- The project ran from 1954. A draft specification was finished in November 1954, the first manual appeared in October 1956, and the compiler was delivered in April 1957 for the IBM 704.
- The name is short for FORmula TRANslation.
- The team knew the project would fail unless the output was fast. Programmers would not accept a 30 per cent penalty on a machine costing a fortune per hour.
- So most of the effort went not into the language but into the optimizer, the part that makes the generated code good.
- It worked. FORTRAN produced code close enough to hand-written assembly that experienced programmers accepted it.
- Within a few years, writing scientific programs in assembly became a strange thing to do. That is the moment high-level programming won.
PLAIN15.7.2 a picture in your head#
- Imagine the first automatic gearbox. Every racing driver says a human changes gear better.
- If it is clumsy and slow they are right, and it fails.
- The FORTRAN team spent their effort making the gearbox change gear as well as a good driver, not on making the steering wheel prettier.
- Once it did, the argument stopped being about speed and became about who wants to change gear 40,000 times on a journey.
Where this comparison breaks: an automatic and a manual gearbox drive the same car. A compiler changes what you can express, not just your comfort. Whole classes of program became possible because nobody had to track a thousand addresses by hand.
PLAIN15.7.3 a worked example#
- Here is a small, period-authentic FORTRAN program that adds 1 to 5 and prints the total. Compare it with the 6502 assembly earlier in this chapter.
C ADD THE WHOLE NUMBERS 1 TO 5 AND PRINT THE TOTAL
ITOTAL = 0
DO 10 I = 1, 5
ITOTAL = ITOTAL + I
10 CONTINUE
PRINT 20, ITOTAL
20 FORMAT (9H TOTAL = , I3)
STOP
END
- Line 1 starts with C in column 1, which marks a comment. That is a card convention: the whole language is laid out for 80-column cards.
- Columns 1 to 5 hold a statement number, column 6 marks a continuation card, columns 7 to 72 hold the statement, and columns 73 to 80 are ignored because that is where the card sequence number went.
ITOTALis an integer with no declaration. In FORTRAN a name beginning with I, J, K, L, M or N is an integer by default; everything else is real.DO 10 I = 1, 5means repeat down to statement 10 with I taking the values 1 to 5.9H TOTAL =is a Hollerith constant: the 9 says the next 9 characters are literal text. Quoted strings arrived later, in FORTRAN 77.- Nine lines. The equivalent assembly is several dozen, and the assembly does not survive a change of computer.
PLAIN15.7.4 what is really happening inside#
- The FORTRAN compiler had to do the four hard jobs listed earlier in this chapter, on a machine with 4,096 or 8,192 words of memory.
- First it read a statement and worked out the structure of the expression, deciding what binds to what.
- Then it turned
DOloops into counters, comparisons and jumps, and turned array subscripts into address arithmetic. - Then came the part that mattered: deciding which values to keep in the 704’s three index registers rather than reloading them from memory.
- It also did what we now call common subexpression elimination and loop invariant motion: compute a thing once, and move work that does not change out of the loop.
- Those techniques were essentially invented here, for this compiler, because there was no choice.
- The compiler ran in several separate passes, reading and rewriting the program from tape between passes, because it could not all fit in memory.
TECHNICAL15.7.5 the engineer’s version#
- Backus’s team at IBM included Irving Ziller, Harlan Herrick, Robert Nelson, Roy Nutt, Sheldon Best, Richard Goldberg, Lois Haibt, David Sayre, Peter Sheridan and Harold Stern.
- The effort is commonly cited at about 18 person-years over roughly three years for the original IBM 704 compiler.
- Target machine: the IBM 704, a 36-bit word machine with hardware floating point, 3 index registers, and typically 4,096 to 32,768 words of core.
| Version | Year | Notable addition |
|---|---|---|
| FORTRAN | 1957 | first delivery, IBM 704 |
| FORTRAN II | 1958 | user subroutines, functions |
| FORTRAN IV | 1962 | machine independence push |
| FORTRAN 66 | 1966 | first ANSI standard |
| FORTRAN 77 | 1978 | IF-THEN-ELSE, strings |
| Fortran 90 | 1991 | free form, array syntax |
| Fortran 2023 | 2023 | current ISO standard |
- FORTRAN 66 was the first standardized programming language in history. That is a standard in the strict sense: a written specification adopted by a standards body.
- Backus received the ACM Turing Award in 1977 for FORTRAN. He had earlier written Speedcoding for the IBM 701 in 1953, an interpreted system, which taught him how badly interpretation cost.
- Fortran is not a museum piece. As of 2026 it remains standard in weather forecasting, computational fluid dynamics, nuclear engineering and climate modelling, and the LINPACK and LAPACK numerical libraries beneath a great deal of scientific software began in Fortran.
The honest version: FORTRAN was neither the first high-level language nor the first compiler. It was the first that people used in large numbers, which is a different and more important claim. Autocode and Laning-Zierler came first and were barely adopted.
WORDS15.7.6 remember these#
- FORTRAN — formula translation — IBM’s 1957 scientific language, the first widely adopted high-level language.
- Optimizer — the part that makes code fast — the compiler passes performing semantics-preserving transformations.
- Implicit typing — the language guessing a variable’s type from its name — FORTRAN’s I-to-N integer rule, switchable off with IMPLICIT NONE.
- Fixed-form source — code laid out in fixed columns — label 1-5, continuation 6, statement 7-72, from the punched card.
- Loop invariant motion — moving unchanging work out of a loop — a classic optimization introduced in the 1957 FORTRAN compiler.
15.8 COBOL, LISP and ALGOL: three different futures#
PLAIN15.8.1 in simple words#
- Between 1958 and 1960 three languages appeared that between them set the shape of nearly everything since.
- COBOL was for business. It reads like English sentences and is built around records, files and exact decimal money.
- LISP was for symbols and for thinking about thinking. It is built around lists and functions, and programs in it are themselves lists.
- ALGOL was for describing algorithms clearly. It was never widely used to run real work, and almost every modern language is its descendant.
- COBOL came from a committee organized by the United States Department of Defense in 1959, with Grace Hopper as a technical adviser.
- LISP came from one man, John McCarthy, at MIT in 1958.
- ALGOL came from a joint European and American committee, and produced the ALGOL 60 report in January 1960.
PLAIN15.8.2 a picture in your head#
- Think of three documents: a company’s accounting ledger, a mathematician’s notebook, and a legal statute.
- COBOL is the ledger. Every field has a fixed size, every amount has exactly two decimal places, and it must balance.
- LISP is the notebook. Everything is written in one simple form, and you are free to write notes about your own notes.
- ALGOL is the statute: a precise written definition of what the words mean, published so anyone can implement it exactly.
Where this comparison breaks: ALGOL 60 was a real running language, not just a document. But its lasting effect really is definitional, because the ALGOL 60 report taught the world how to specify a language properly.
PLAIN15.8.3 a worked example#
- Here is COBOL. The shape is deliberately unlike everything else.
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYTOTAL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-TOTAL PIC 9(7)V99 VALUE ZERO.
01 WS-AMOUNT PIC 9(5)V99 VALUE 125.50.
PROCEDURE DIVISION.
ADD WS-AMOUNT TO WS-TOTAL.
DISPLAY "TOTAL IS " WS-TOTAL.
STOP RUN.
PIC 9(7)V99means seven digits, then an assumed decimal point, then two digits. The V is not stored; it marks where the point sits.- That single feature is why COBOL still runs banks. It stores money as exact decimal digits, not binary floating point, so 0.10 plus 0.20 is exactly 0.30 and never 0.30000000000000004.
- Here is LISP. The whole language is this one shape.
(defun sum-to (n)
(if (= n 0)
0
(+ n (sum-to (- n 1)))))
(sum-to 5) ; gives 15
- Every LISP expression is a list in brackets: the first item is the operation, the rest are its arguments. That is all the syntax there is.
- Because a program is a list, a program can build and run another program with no special machinery. That property is homoiconicity.
PLAIN15.8.4 what is really happening inside#
- COBOL’s committee met at the Pentagon on 28 and 29 May 1959 with 41 attendees, chaired by Charles Phillips. An earlier meeting had been convened by Mary K. Hawes on 8 April 1959.
- The goal was one language running on machines from every manufacturer, so the government would stop paying to rewrite the same payroll six times.
- Grace Hopper was a technical adviser, not a committee member. Her FLOW-MATIC was the single strongest influence on the design.
- Jean Sammet, who was on the committee, put the record straight bluntly: Hopper was not the mother, creator or developer of COBOL.
- LISP started differently. McCarthy wrote a mathematical notation in a 1960 paper and did not intend it as a real language.
- Steve Russell read the paper, realized the
evalfunction described in it was itself an interpreter, and hand-compiled it into IBM 704 machine code. LISP became real by accident. - Two 704 assembly macros gave LISP two permanent words:
carfor the first item andcdrfor the rest. - ALGOL’s contribution is structural: blocks marked
beginandend, names visible only inside the block where they are declared, and procedures that can call themselves. - If your language has curly brackets, local variables and recursion, it is an ALGOL descendant. C, Java, JavaScript, Python, Go and Rust all are.
TECHNICAL15.8.5 the engineer’s version#
- COBOL: COmmon Business-Oriented Language. The COBOL 60 specification was approved by the CODASYL executive committee on 8 January 1960. The first COBOL program ran on an RCA 501 on 17 August 1960.
- In December 1960 the same COBOL program ran on both an RCA and a UNIVAC machine. That cross-vendor portability demonstration was the point of the whole exercise.
| Figure | Value | Source and date |
|---|---|---|
| Lines of COBOL in use | 200 billion | Gartner estimate, 1997 |
| Business programs run | about 80% | Gartner estimate, 1997 |
| Card swipes touching it | about 95% | widely cited, 2020 |
- Treat newer figures with care. Claims such as “COBOL handles 3 trillion dollars of transactions a day” circulate widely and trace back to vendor material rather than an audited study.
- The safe statement is that COBOL still runs core banking, insurance, payroll and government systems in 2026, and nobody has a credible plan to remove most of it.
- LISP: John McCarthy, MIT, from 1958. Key paper: “Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I”, 1960. LISP introduced automatic garbage collection, dynamic typing, higher-order functions, the read-eval-print loop, and code as data.
- LISP is the second-oldest high-level language still in use, after Fortran. Living dialects include Common Lisp, Scheme, Racket and Clojure.
- ALGOL 58, originally called IAL, came from a Zurich meeting in 1958. ALGOL 60 came from a Paris meeting in January 1960 with 13 authors: Bauer, Naur, Rutishauser, Samelson, Vauquois, van Wijngaarden and Woodger from Europe, and Backus, Green, Katz, McCarthy, Perlis and Wegstein from the United States. Peter Naur edited the report.
- The report’s grammar notation, invented by Backus and refined by Naur, is Backus-Naur Form. It is still how language grammars are written in 2026.
- Tony Hoare’s verdict on ALGOL 60 is the most quoted line in language design: a language so far ahead of its time that it was an improvement not only on its predecessors but on nearly all its successors.
WORDS15.8.6 remember these#
- COBOL — the English-like business language — CODASYL, 1959 to 1960, built on records, files and fixed-point decimal.
- PICTURE clause — the description of a field’s exact shape — COBOL’s PIC notation defining digits, sign and implied decimal point.
- LISP — the list language — McCarthy, 1958: s-expressions, garbage collection and code as data.
- Homoiconicity — programs made of the same stuff as data — source represented directly in the language’s own data structures.
- ALGOL — the algorithm description language — ALGOL 58 and 60, source of block structure, lexical scope and recursion.
- Backus-Naur Form — the standard way of writing a grammar — a metasyntax for context-free grammars, from the ALGOL 60 report.
15.9 The moth, and what a bug really is#
PLAIN15.9.1 in simple words#
- On 9 September 1947, operators of the Harvard Mark II found the machine giving wrong answers.
- They traced the fault to relay number 70 in panel F, and found a moth caught between the contacts.
- They removed the moth, taped it into the logbook, and wrote beside it: “First actual case of bug being found.”
- That logbook page, moth still attached, is at the Smithsonian’s National Museum of American History.
- It is a lovely story and it is almost always told wrongly.
- The word “bug” for a fault did not start there. It was already old engineering slang.
- Thomas Edison used it in writing in 1878, describing how little faults and difficulties, “as such little faults and difficulties are called”, show themselves and take months to clear.
- The joke in the logbook only works because everyone already used the word. For once they had found an actual, literal bug.
- Grace Hopper was associated with the Mark II team and told the story for decades. Accounts differ on whether she was in the room, and the entry is generally attributed to others on the team.
PLAIN15.9.2 a picture in your head#
- Imagine a workshop where people have called every annoying fault a “gremlin” for seventy years.
- One day someone opens a machine and finds a small carved gremlin figure that a child dropped in.
- They pin it to the wall and write “first actual gremlin found”. Everyone laughs, because the word was already worn smooth.
- A century later people say “that is where the word gremlin comes from”, which reverses the joke completely.
Where this comparison breaks: unlike gremlins, insects really did cause failures in relay machines. Relay contacts were open, mechanical and warm, and buildings were not sealed. It was a genuine failure mode, not a one-off.
PLAIN15.9.3 a worked example#
- Now the harder question. How did you debug in 1949, when there was no screen and printing a line cost machine time you did not have?
- Method one: the console lights. A row of lamps showed the accumulator or the program counter in binary, and you read the bits.
- Method two: single step. A switch made the machine execute one instruction per button press, so you could watch a register change.
- Method three: the post-mortem routine. A small program left in memory that, after your program stopped, printed a chosen block of memory.
- Method four: the checking routine, or trace. A program that ran yours one instruction at a time and printed what each did. Stanley Gill described this for EDSAC in a 1951 paper on diagnosing mistakes in programmes.
- Method five: sound. EDSAC and the Ferranti Mark 1 had a loudspeaker wired to a bit of a register. Programmers learned the sound of a healthy program and heard a stuck loop instantly.
- Method six: desk checking. You read your own code on paper, pretending to be the machine, writing register values in a column.
- All six survive today, renamed: registers view, single step, core dump, instruction trace, profiling by observation, and code review.
PLAIN15.9.4 what is really happening inside#
- A trace routine is really an interpreter. It fetches one of your instructions, prints it, performs it itself, and moves on.
- A post-mortem dump is a different idea. It does not slow your program at all. It captures the wreckage afterwards.
- That trade-off has never gone away. It is exactly the choice between running under a debugger and reading a crash dump.
- Breakpoints were originally physical. You replaced an instruction in memory with a halt, ran until the machine stopped, read the lights, then put the original instruction back.
- Modern debuggers do the identical trick. On x86 a breakpoint is the single byte CC, the INT 3 instruction, written over your code and restored when execution stops.
TECHNICAL15.9.5 the engineer’s version#
- Harvard Mark II: an electromechanical relay machine completed in 1947 for the United States Navy at Dahlgren, Virginia, built by Howard Aiken’s group.
- The 9 September 1947 log entry sits at 15:45 in the logbook. The relay is recorded as Relay 70, Panel F.
- Earlier uses of “bug”: Edison’s 1878 letter; the 1896 edition of Hawkins’ New Catechism of Electricity defines “bug” as a fault or trouble in an apparatus.
- The term was standard in radio and telephony by the 1920s, and “debug” is documented in aviation in the 1940s, before the moth.
- Terminology today, precisely: a fault is the defect in the code, an error is the wrong internal state it causes, and a failure is the externally visible wrong behaviour. That three-level split is standard in dependability engineering.
- Tools that replaced the console lights:
gdbandlldbfor interactive debugging,straceanddtracefor system call tracing,perffor sampling,valgrindand AddressSanitizer for memory errors, and core dumps controlled byulimit -cand/proc/sys/kernel/core_patternon Linux.
The honest version: the popular claim “the word bug comes from a moth in a computer in 1947” is simply false, and the people who wrote the log entry knew it, which is exactly why they wrote “first actual case”. The story is true; the etymology attached to it is not.
WORDS15.9.6 remember these#
- Bug — a fault in a program — a defect in source or design; the word is engineering slang predating computing by at least 70 years.
- Debugging — finding and removing faults — systematic fault localization, from observed failure back to defect.
- Post-mortem dump — a printout of memory after a crash — a core dump, the captured process image at failure time.
- Trace — a record of each step performed — an instruction-level execution log, historically produced by interpretation.
- Breakpoint — a place where the machine stops for you — a trap instruction patched over the target instruction, restored on hit.
- Fault, error, failure — the defect, the bad state, the visible wrongness — the standard three-level dependability vocabulary.
15.10 The rise of the operating system as software#
PLAIN15.10.1 in simple words#
- In the early 1950s there was no operating system, because there was nothing for one to do.
- One program ran at a time, and a human being was the operating system.
- The machine sat idle during all of that, and the machine was the expensive part.
- So people wrote a small program that stayed in memory permanently and did the operator’s job: read the next job, run it, clean up, read the next.
- That resident program was called a monitor, and it is the ancestor of every operating system.
- The next problem was worse. A program waiting for a tape to rewind left the processor idle for seconds at a time.
- The answer was to keep several programs in memory and switch to another whenever the current one had to wait.
- Then came the obvious next question: if we can switch between programs, we can switch between people. Give everyone a terminal and take turns. That is time sharing.
PLAIN15.10.2 a picture in your head#
- Think of one very expensive oven in a village.
- At first each family carries its dish in, lights the oven, cooks, and carries it out, and the oven cools between families.
- Then the village hires a permanent baker who keeps the oven hot and takes dishes in a queue. That is the batch monitor.
- Then the baker puts several dishes in at once, turning to whichever needs attention. That is multiprogramming.
- Then the baker gives every family thirty seconds of attention in rotation, so each feels the oven is theirs. That is time sharing.
Where this comparison breaks: the oven’s heat is genuinely shared, whereas a processor gives each program the whole machine for a short slice. The illusion of simultaneity comes from switching faster than a human can notice, not from dividing capacity.
PLAIN15.10.3 a worked example#
- Consider a 1957 job on an IBM 704 that computes for 2 seconds.
- Without a monitor: 4 minutes of operator handling, 2 seconds of computing. Machine utilization is under 1 per cent.
- With a batch monitor and a stack of jobs on one tape: handling drops to under a second per job, and utilization rises above 50 per cent.
- With multiprogramming: while job A waits 30 milliseconds for a disk, job B uses those 30 milliseconds, and utilization approaches 90 per cent.
- With time sharing: 30 users each get slices of about 100 milliseconds, and each feels alone on the machine as long as none is doing heavy work.
- The economics justify the complexity. A machine costing tens of thousands of dollars a month sitting idle at 1 per cent is a catastrophe, and that is why operating systems exist at all.
PLAIN15.10.4 what is really happening inside#
- A monitor needs three abilities, and each one required new hardware.
- It must regain control from a program that will not stop. That needs a timer interrupt: a clock that forces the processor into the monitor.
- It must stop one program corrupting another. That needs memory protection: hardware that checks every address.
- It must stop a program driving the tape drive directly. That needs privileged mode: some instructions work only for the monitor.
- Those three inventions are the boundary between a program and an operating system. Without them, a monitor is only a convention programs may ignore.
- The word “kernel” means exactly this: the part that runs in privileged mode and that everything else must go through.
TECHNICAL15.10.5 the engineer’s version#
- GM-NAA I/O, written in 1956 by Robert Patrick of General Motors Research and Owen Mock of North American Aviation for the IBM 704, is generally described as the first operating system.
- It was followed by the FORTRAN Monitor System, then IBSYS on the IBM 7090 and 7094 family.
- Job Control Language exists because a batch monitor must be told where one job ends and the next begins. IBM’s JCL statements still start with two slashes in columns 1 and 2, a punched-card artefact.
- CTSS, the Compatible Time-Sharing System, was first demonstrated by Fernando Corbato at MIT in November 1961 on an IBM 709, with three user consoles.
- It moved to an IBM 7090 in 1962 and a 7094 later, entered routine service in summer 1963, and could support up to 112 teleprinter terminals through an IBM 7750 controller.
- CTSS was the first system with password login, and carried some of the first electronic mail and text formatting tools.
- Multics, from 1965, was the joint MIT, General Electric and Bell Labs successor. It introduced segmented virtual memory, a hierarchical file system, dynamic linking and rings of protection.
- Multics was late, huge and slow to arrive, and Bell Labs withdrew in 1969. That withdrawal directly caused UNIX, which is the next section.
| System | Year | Idea it added |
|---|---|---|
| GM-NAA I/O | 1956 | resident batch monitor |
| IBSYS | 1960 | full job stream management |
| CTSS | 1961 | interactive time sharing |
| Multics | 1965 | virtual memory, protect rings |
- Chapter 18 takes this up properly: scheduling, virtual memory, system calls and modern kernels. Here we needed only the reason the operating system had to become software in the first place.
WORDS15.10.6 remember these#
- Monitor — the small permanent program that runs jobs — the resident supervisor of a batch system.
- Batch — jobs run back to back with no user present — non-interactive scheduling from a job queue.
- Multiprogramming — several programs in memory, one running — overlapping input and output with computation.
- Time sharing — many people using one machine at once — preemptive scheduling with short quanta over interactive terminals.
- Kernel — the privileged core of the operating system — code executing in supervisor mode, mediating hardware access.
- Privileged mode — an instruction level only the system may use — supervisor or ring 0 execution enforced by the processor.
15.11 UNIX and C#
PLAIN15.11.1 in simple words#
- In 1969 Bell Labs pulled out of Multics, and Ken Thompson had a large, ambitious operating system project taken away from him.
- He had written a game called Space Travel and wanted somewhere to run it. He found a little-used PDP-7 in a corner.
- With Dennis Ritchie and others, and with a month of free time while his wife was away, he wrote a tiny operating system for it.
- It had a hierarchical file system, processes and a small set of tools. It was called Unics as a joke on Multics, and the spelling settled as UNIX.
- UNIX was written in assembly at first, like everything else.
- Then came the radical part. Thompson wrote a language called B, and Ritchie grew it into a language called C between 1971 and 1973.
- In 1973 they rewrote the UNIX kernel itself in C.
- Nobody did that. An operating system had to be assembly, because it touches hardware and must be fast.
- But it worked, and the consequence was enormous: to move UNIX to a new computer you now wrote a C compiler for it, not a whole new operating system.
- That is where portable software begins.
PLAIN15.11.2 a picture in your head#
- Imagine every city building its trains to a different rail gauge, so every train must be rebuilt from scratch to move city to city.
- Now someone builds an adjustable axle. The carriage design stays the same; only the axle is refitted.
- C is the adjustable axle. The compiler is refitted per machine, and the software above it moves across.
- The carriage is not perfectly identical everywhere. Some of it still has to be adjusted by hand, and the parts touching the rails always do.
Where this comparison breaks: C’s portability is not automatic, it is a discipline. C deliberately leaves things such as integer size and byte order unspecified, and code assuming one machine’s answers is not portable, no matter that it is written in C.
PLAIN15.11.3 a worked example#
- Here is the same “add 1 to n” job from earlier, written in C, next to what a compiler produces for it.
int sum_to(int n) {
int total = 0;
for (int i = 1; i <= n; i++)
total += i;
return total;
}
- Below is the x86-64 assembly from GCC 13.3.0 with optimization turned off, in Intel syntax. Six lines of C become nineteen instructions.
sum_to:
push rbp
mov rbp, rsp
mov DWORD PTR -20[rbp], edi ; save n
mov DWORD PTR -8[rbp], 0 ; total = 0
mov DWORD PTR -4[rbp], 1 ; i = 1
jmp .L2
.L3:
mov eax, DWORD PTR -4[rbp] ; load i
add DWORD PTR -8[rbp], eax ; total += i
add DWORD PTR -4[rbp], 1 ; i++
.L2:
mov eax, DWORD PTR -4[rbp] ; load i
cmp eax, DWORD PTR -20[rbp] ; compare with n
jle .L3 ; loop if i <= n
mov eax, DWORD PTR -8[rbp] ; return total
pop rbp
ret
- Notice
.L2and.L3. Those are labels, exactly the idea from the 6502 assembly earlier in this chapter. The compiler invents them, so no human counts bytes. - Notice the loop is compiled with the test at the bottom and one jump into it. That shape is a choice the compiler made, not something you wrote.
- Turn optimization on and the function changes completely: the compiler unrolls the loop and computes two values per pass. That is the compiler choosing, which an assembler never does.
- You can see this on any Linux machine with
gcc -S -masm=intel -O0 file.cand thengcc -S -masm=intel -O2 file.c.
PLAIN15.11.4 what is really happening inside#
- C was designed to sit exactly one small step above the machine, and no higher.
- Its types map onto machine word sizes, its pointers are memory addresses, and its arrays are pointer arithmetic in disguise.
- That closeness is why a C compiler is small and easy to write for a new processor, and why UNIX could be moved.
- It is also why C is dangerous. There is no bounds checking, because the machine has none, and the language does not add what the machine lacks.
- The 1973 rewrite made the UNIX kernel about a third larger and somewhat slower than the assembly version, and Thompson and Ritchie accepted that trade deliberately.
- They got back something worth far more: they could read their own kernel, change it safely, and move it.
- In 1978 Brian Kernighan and Dennis Ritchie published “The C Programming Language”. The book was so precise and so short that it became the definition of the language for over a decade, known simply as K and R.
TECHNICAL15.11.5 the engineer’s version#
- Timeline: Bell Labs left Multics in 1969; UNIX started on a PDP-7 in 1969; moved to a PDP-11/20 in 1970; C developed from B and BCPL through 1971 and 1972; Version 4 UNIX rewritten in C in 1973.
- The paper by Ritchie and Thompson, presented at the ACM Symposium on Operating Systems Principles in 1973 and published in Communications of the ACM in July 1974, is the announcement that made UNIX famous.
- Version 6 UNIX, released in 1975, was licensed cheaply to universities. John Lions’s 1976 commentary on its source code was for years the most photocopied document in computing.
- UNIX’s design rules became a culture: everything is a file, programs do one thing, programs are joined by pipes, and text is the universal interface.
- C standards: K and R C from 1978, ANSI X3.159-1989 (C89), ISO/IEC 9899:1990 (C90), then C99, C11, C17, and C23 published in 2024.
| Year | Event | People |
|---|---|---|
| 1969 | Bell Labs leaves Multics | Bell Labs |
| 1969 | UNIX begins on a PDP-7 | Thompson, Ritchie |
| 1972 | C takes shape | Ritchie |
| 1973 | UNIX kernel rewritten in C | Thompson, Ritchie |
| 1978 | The C Programming Language | Kernighan, Ritchie |
- Thompson and Ritchie received the ACM Turing Award in 1983.
- As of 2026 the direct descendants of this work include Linux, the BSDs, macOS and iOS (through NeXTSTEP and BSD), and Android’s userspace model. The POSIX standards, IEEE 1003, are the written form of the UNIX interface.
The honest version: C is not portable in the sense people usually mean. The standard deliberately leaves behaviour unspecified, undefined or implementation-defined in hundreds of places. What C gives you is a portable language with a small compiler, not portable programs for free.
WORDS15.11.6 remember these#
- UNIX — the small operating system from Bell Labs, 1969 — a multi-user, multi-process system whose interface is standardized as POSIX.
- C — the language UNIX was rewritten in, 1972 — a statically typed systems language with direct memory access and manual lifetime management.
- Portability — software that moves between machines — source compatibility given a conforming compiler and defined behaviour.
- The 1973 rewrite — the moment an operating system stopped being assembly — Version 4 UNIX in C, trading size and speed for maintainability.
- K and R — the 1978 book that defined C — Kernighan and Ritchie, “The C Programming Language”, the pre-standard reference.
15.12 How software was shared, and then sold#
PLAIN15.12.1 in simple words#
- For the first fifteen years, software was not sold. It came free with the computer, because the computer was the product.
- Users swapped programs directly. IBM’s user group SHARE, founded in 1955, ran a library that members contributed to and drew from.
- In 1969 IBM changed that. Facing antitrust pressure, it announced it would price software separately from hardware. That decision, effective in 1970, is where the software industry begins.
- When home computers arrived in the mid-1970s, sharing came back, because the people involved were hobbyists with no money.
- Magazines printed the full source code of programs, and you typed them in by hand, then hunted for your own typing mistakes.
- The Homebrew Computer Club, first meeting on 5 March 1975 in a garage in Menlo Park, California, was the centre of this. Members copied paper tapes and passed them round freely.
- In January 1976 a 20-year-old Bill Gates wrote an angry letter to that community, saying most of them were stealing his BASIC and that this would stop anyone writing good software.
- He was making an argument nobody had needed to make before: that software by itself is a product you buy.
- Later, others argued the opposite just as forcefully, and built an entire parallel world on it.
PLAIN15.12.2 a picture in your head#
- Think of recipes. For centuries they spread freely; cooks copied them, improved them and passed them on.
- Then someone opens a restaurant and says the recipe is the business, not the meal, and copying it is theft.
- Some cooks agree and buy licences. Others say a recipe you may not read or change is not a recipe at all, and start a movement to keep them open.
- Both worlds now exist side by side, and most restaurants use some of each.
Where this comparison breaks: recipes are not protected by copyright in most places, whereas software source code clearly is. The legal ground under the argument is completely different, and that is why licences, not manners, ended up deciding it.
PLAIN15.12.3 a worked example#
- Here is what “sharing software” physically meant, in order of era.
- 1955 to 1968: a magnetic tape posted to a user group, and a printed catalogue of routines you could request.
- 1975 to 1979: a punched paper tape passed hand to hand at a club meeting, or a program listing printed in a magazine that you typed in yourself.
- 1978 to 1990: a floppy disk, posted or copied at a club, and later a bulletin board system you dialled with a modem at 300 or 1,200 bits per second.
- 1991 onwards: an FTP site, then the web, then a version control server.
- 2008 onwards: a public git repository, which is where nearly all of it lives in 2026.
- The pattern is constant. Each drop in the cost of copying produced a burst of sharing, and a matching argument about payment.
PLAIN15.12.4 what is really happening inside#
- Gates’s letter is worth understanding rather than cheering or booing.
- The facts he cited: MITS was shipping about 1,000 Altair computers a month at the end of 1975, while paid copies of BASIC numbered in the low hundreds.
- He said about 40,000 dollars of computer time went into writing it, and that the royalty worked out at roughly two dollars an hour for the work.
- Critics answered that the computer time figure was inflated accounting, and that Microsoft’s BASIC had itself been developed on a university machine.
- Both things can be true. The letter is still the clearest early statement that software has a development cost that must be paid for somehow.
- In 1983 Richard Stallman made the opposite argument, prompted by a printer whose driver he was not allowed to fix.
- His answer was not to ask nicely. It was a licence that used copyright law against itself: you may copy and change this, provided anything you distribute carries the same permission.
- That trick is called copyleft, and it is the mechanism, not the slogan, that made free software durable.
TECHNICAL15.12.5 the engineer’s version#
- IBM’s unbundling announcement came on 23 June 1969 and took effect in January 1970. Before it, software and support were included in the hardware price; after it, they were priced separately.
- Homebrew Computer Club: first meeting 5 March 1975, Gordon French’s garage, Menlo Park. The Altair 8800 had appeared on the cover of Popular Electronics dated January 1975.
- A pre-release paper tape of Altair BASIC went missing at a MITS event in Palo Alto in June 1975; Dan Sokol duplicated it, and about 50 copies appeared at the next Homebrew meeting.
- Gates wrote “An Open Letter to Hobbyists” in January 1976. It was published in the Homebrew Computer Club Newsletter dated 3 February 1976 and in MITS Computer Notes for February 1976, and reprinted widely.
- Richard Stallman announced the GNU Project, a recursive joke standing for “GNU’s Not Unix”, in a Usenet message on 27 September 1983. Development began January 1984, the GNU Manifesto appeared in 1985, and the Free Software Foundation was founded in October 1985.
| Licence | Year | Core idea |
|---|---|---|
| GPL version 1 | 1989 | copyleft, source must follow |
| GPL version 2 | 1991 | the Linux kernel licence |
| GPL version 3 | 2007 | patents and locked hardware |
| MIT / BSD | 1980s | permissive, no copyleft |
- The four freedoms of free software: run the program for any purpose, study and change it, redistribute copies, and distribute your modified versions. Access to source code is a precondition of the second and fourth.
- Linus Torvalds posted his announcement to the comp.os.minix newsgroup on 25 August 1991, describing a free operating system as “just a hobby, won’t be big and professional like gnu”. Version 0.01 followed on 17 September 1991.
- Linux moved to the GPL with version 0.12 in February 1992 and reached version 1.0 in March 1994. Combining the Linux kernel with the GNU tools produced the first complete free operating system.
- The term “open source” was coined at a meeting in Palo Alto on 3 February 1998, following Netscape’s decision to release its browser source. The Open Source Initiative was founded that month.
- Free software and open source are not synonyms, and the disagreement is real rather than pedantic. Free software is an ethical argument about user freedom. Open source is an argument about development quality and business practicality. They mostly cover the same code.
WORDS15.12.6 remember these#
- Unbundling — selling software separately from hardware — IBM’s 1969 announcement, the origin of the commercial software industry.
- Copyleft — a licence that forces the freedom onward — a reciprocal licence requiring derivative distributions under the same terms.
- GPL — the GNU General Public License — the reciprocal licence family, versions 1 (1989), 2 (1991) and 3 (2007).
- Permissive licence — you may do almost anything — MIT and BSD style terms with attribution but no reciprocity.
- Free software — free as in freedom, not price — the four freedoms defined by the Free Software Foundation.
- Open source — publicly readable and modifiable code — the Open Source Initiative definition, from 1998.
15.13 A short history of the idea of a “programmer”#
PLAIN15.13.1 in simple words#
- Before 1945, “computer” was a job title for a person, usually a woman, who did calculations with a desk machine.
- The first people to program electronic machines were drawn from that pool and were called operators, not programmers.
- The work was thought of as clerical, because the design of the machine was assumed to be the intellectual part.
- That was badly wrong, and it took about fifteen years to correct.
- Through the 1950s the word “programmer” settled in, and “coder” came to mean a junior who turned someone else’s plan into instructions.
- By the mid-1960s, projects had grown so large that they routinely failed. Systems were years late, far over budget, and full of faults.
- In 1968 a NATO conference gave that a name: the software crisis. It also made popular a deliberately provocative term for the cure: software engineering.
- The provocation was the point. If bridges can be engineered with method and discipline, why not programs.
- Almost sixty years later the argument is unfinished, and it is still the most useful question in the field.
PLAIN15.13.2 a picture in your head#
- Think of building. First there were people who put up a shed, and it stood up or it did not.
- Then buildings got taller, and a shed-builder’s instincts stopped scaling. People fell.
- So the trade split: architects, structural engineers, surveyors, inspectors, codes of practice and licences.
- Software went through the first two stages and got stuck partway through the third.
Where this comparison breaks: a bridge’s load is physics and does not argue. A program’s requirements change every week, and it is expected to be modified constantly for decades. No civil engineer is asked to change the span of a finished bridge on a Thursday.
PLAIN15.13.3 a worked example#
- The example everyone in 1968 had in mind was IBM’s OS/360, the operating system for the System/360 family announced in 1964.
- It ran to thousands of people and years of delay, and adding people made it later, not earlier.
- Fred Brooks, who managed it, wrote up the lessons in “The Mythical Man-Month” in 1975.
- His central observation: a task that takes 12 months for 1 person does not take 1 month for 12 people, because they must all talk to each other.
- With n people there are n times (n minus 1) divided by 2 communication paths. For 12 people that is 66. For 50 people it is 1,225.
- Brooks’s law, in his own compressed form: adding people to a late software project makes it later.
- That is the sharpest single sentence about software management ever written, and it is still true in 2026.
PLAIN15.13.4 what is really happening inside#
- The 1968 conference proposed answers that are now everyday practice: specification before coding, modular design, reviews, testing as a distinct activity, and measurement.
- Alongside it, a related movement argued that programs should be structured so a human can reason about them.
- Edsger Dijkstra’s letter “Go To Statement Considered Harmful”, published in Communications of the ACM in March 1968, is the famous shot in that campaign.
- His argument was not aesthetic. It was that with unrestricted jumps you cannot look at a line of code and know how you got there, so you cannot reason about the program at all.
- What replaced the goto was exactly the block structure ALGOL 60 had introduced: sequence, choice and loops with one way in and one way out.
- So the theory and the management story meet here. Structured programming was a response to a management crisis.
TECHNICAL15.13.5 the engineer’s version#
- The earliest known use in print of “software” in the modern sense is by John Tukey, in “The Teaching of Concrete Mathematics”, American Mathematical Monthly, January 1958.
- The NATO Software Engineering Conference was held at Garmisch, Germany, from 7 to 11 October 1968, with roughly 50 participants. A second conference followed at Rome in October 1969.
- Who coined “software engineering” is genuinely disputed. Margaret Hamilton, who led the Apollo onboard flight software at the MIT Instrumentation Laboratory, states she began using the term during Apollo in the mid-1960s.
- Anthony Oettinger used it in an ACM president’s letter in 1966, and the 1968 NATO conference made it general.
- All three claims can be accurate at once, and the safe statement is that the 1968 conference established the term.
- Dijkstra’s 1972 Turing Award lecture summarized the crisis: with no machines there was no programming problem, with weak machines a mild one, and with powerful machines an equally gigantic one.
- A 1968 study by Sackman, Erikson and Grant reported differences of an order of magnitude or more between individual programmers on the same task.
- The headline “10x programmer” comes from that work. Its method has been criticized ever since, so the size of the effect is active debate rather than established fact.
| Year | Term or event | Significance |
|---|---|---|
| 1946 | “operator” | programming seen as clerical |
| 1958 | “software” in print | Tukey, AMM, January 1958 |
| 1968 | NATO Garmisch | “software engineering” named |
| 1968 | Go To Considered Harmful | structured programming |
| 1975 | The Mythical Man-Month | Brooks, on team scaling |
The honest version: software engineering is still not engineering in the sense that civil engineering is. There is no universal licensure, no legally binding code of practice in most jurisdictions, and no agreed body of predictive knowledge saying how long a given program will take. Experts genuinely disagree on whether that is a failing to be fixed or a reflection of a different kind of work.
WORDS15.13.6 remember these#
- Software — the instructions, not the machine — programs and data as distinct from hardware; earliest known print use, Tukey, 1958.
- Software crisis — projects late, costly and broken — the recognition, named in 1968, that project growth outran available method.
- Software engineering — treating programming as a disciplined craft — the application of engineering method to software, named at NATO 1968.
- Brooks’s law — adding people to a late project makes it later — the communication overhead of n(n-1)/2 channels swamps added capacity.
- Structured programming — code shaped so you can reason about it — single entry, single exit constructs replacing arbitrary jumps.
15.98 Common wrong ideas#
- Wrong: a program is a special kind of thing stored differently from data. Right: it is ordinary numbers in ordinary memory, treated as instructions only because the program counter points at them.
- Wrong: Grace Hopper wrote the first compiler as we use the word today. Right: she coined the word and built A-0 in 1952, which selected, relocated and joined library routines. That is a linking loader, not a translator.
- Wrong: nothing existed before FORTRAN. Right: Corrado Bohm’s 1951 thesis described a translator on paper, Glennie’s Autocode ran in 1952, and Laning and Zierler’s algebraic system ran on Whirlwind by 1954.
- Wrong: the word “bug” comes from the 1947 moth. Right: Edison used it in 1878, and the logbook entry says “first actual case” precisely because the word was already old slang.
- Wrong: ENIAC took two weeks to reprogram, full stop. Right: planning took weeks, physical setup days and debugging days more, and the 1948 conversion changed the whole picture by cutting setup to hours.
- Wrong: assembly language is always one line to one instruction. Right: macros, pseudo-instructions and assembler-chosen branch widths break that on most real assemblers.
- Wrong: COBOL is obsolete. Right: it still runs core banking, insurance and government payroll in 2026, largely because its exact decimal arithmetic is correct for money in a way binary floating point is not.
- Wrong: high-level languages won because programmers wanted comfort. Right: they won when FORTRAN’s optimizer made the generated code fast enough that the speed objection collapsed.
- Wrong: C is portable, so C programs run anywhere. Right: C is a portable language with a small compiler. Programs depending on integer size, byte order or undefined behaviour are not portable at all.
- Wrong: free software means free of charge. Right: it means the four freedoms to run, study, share and modify. You may sell it, and the Free Software Foundation says so explicitly.
15.99 Chapter summary in 20 lines#
- A program at the bottom is a list of numbers in memory that a processor reads as instructions, one after another.
- Seven bytes on a 6502 make a complete working program, and you can trace it by hand with nothing but an opcode table.
- ENIAC in 1946 had no program storage at all. You wired it with cables and set 1,200-way switch banks, and a change took days.
- Its six principal programmers, McNulty, Jennings, Snyder, Wescoff, Bilas and Lichterman, were classified as operators and taught themselves the machine.
- The 1948 conversion gave ENIAC a stored instruction set and cut setup from days to hours at about a sixfold speed cost.
- Programs then went in as raw numbers: front-panel switches, punched paper tape, and above all the 80-column punched card.
- A card holds 12 rows by 80 columns; a digit is one punch, a letter is a zone punch plus a digit punch, and that is Hollerith encoding.
- Batch processing meant handing a deck to an operator and waiting hours or a day for a printout, so programmers desk-checked everything first.
- Assembly language replaced numbers with mnemonics and hand-counted addresses with labels, and an assembler recomputed the numbers every time.
- EDSAC’s Initial Orders by David Wheeler in 1949, the Wheeler Jump, the 87-routine library, and the 1951 Wilkes, Wheeler and Gill book built the idea of reusable software.
- Assembly is tied to one machine, slow to write and barely checked, so people asked whether a program could write the machine code instead.
- The objection was economic, not snobbish: machine time cost far more than programmer time, so a translator had to lose almost no speed.
- Grace Hopper coined “compiler” and built A-0 in 1952. It gathered subroutines from a tape library, relocated them and joined them, which today we call linking and loading.
- Bohm’s 1951 thesis, Glennie’s 1952 Autocode and the 1954 Laning-Zierler system all have claims to “first compiler” under different definitions.
- FORTRAN, from Backus’s team at IBM, ran from 1954 to delivery in April 1957, and won because its optimizer matched hand-written assembly closely enough for scientists to accept it.
- COBOL came from the CODASYL committee in 1959 with FLOW-MATIC as its main ancestor, and its exact decimal arithmetic keeps it running finance in 2026.
- LISP in 1958 gave us code as data, garbage collection and recursion, and ALGOL 60 gave nearly every later language its block structure.
- The moth of 9 September 1947 is real and is in the Smithsonian, but the word “bug” was already 70 years old when it was taped in.
- Batch monitors from 1956, then CTSS time sharing in 1961 and Multics, made the operating system a permanent program that manages other programs.
- UNIX from 1969 and its 1973 rewrite in C made operating systems portable, and everything since, from Linux in 1991 to the machine in front of you, sits on that foundation.