Lazarus AP · a resurrection in software
Every Shuttle flew with five IBM AP-101 computers — machines slower than a musical greeting card — that steered two thousand tons of spacecraft by voting among themselves. Their programs were written in HAL/S, a language invented for spaceflight and used almost nowhere else.
Below, one small program runs on an emulated AP-101S, one instruction at a time. The program was written this week — but the compiler that turned it into machine code is the real Shuttle compiler, recovered and brought back to life. Nothing here is a mock-up: every number you'll see is the machine actually working.
The AP-101S had about 1 MB of memory and no screen of its own. Five of them ran in lockstep on each orbiter; if one disagreed, the others voted it out mid-flight. This emulator was built from IBM’s original 1,300-page manual, one cited page at a time.
HAL/S looks a little like Fortran with wings. The source of the program below is nine lines: print a greeting, loop three times printing a vote, print a sign-off. The Shuttle’s real flight software was about 400,000 lines of it.
The Shuttle’s compiler survived as punch-card-era source code, restored by the Virtual AGC project. We rebuilt it, compiled a brand-new program with it, and linked it with a tool written for this project. What you’re watching is the result: 401 instructions, the complete run.
Right now:
Instruction tape — the program, one step at a time
Each line is one machine instruction: its address in memory, its name, and what it does. The green line is the one executing now.
Registers — the computer’s short-term memory
Eight slots the CPU thinks with. A value that just changed turns amber — watch R6 count the loop.
Mission console — what the program prints
Text appears here at the exact instruction the program wrote it — the same characters, columns and all, that the real toolchain produces.
For the record
On August 2, 2026 at 12:09 PDT, Keith Adler ran the Space Shuttle’s own square-root routine — RUNASM/SQRT.asm, flown on every mission of the program — on this emulator, assembled by the genuine flight assembler. Input 2.0; answer 1.4142135… (0x4116A09E), exact to the last bit: the same answer it gave Columbia.
Atlantis closed out the fleet on July 21, 2011. As far as this project can establish, these instructions had scarcely executed anywhere since — and never before in this resurrection.
| AP-101S (Shuttle, 1980s) | A recent iPhone | |
| Speed | ~1 million instructions/sec | tens of billions/sec — roughly a million× faster |
| Memory | 1 MB — every byte accounted for | 8 GB — ~8,000× more |
| Weight | ~25 kg per computer, five aboard | ~170 g |
| Power | ~550 W of spacecraft electricity | sips from a pocket battery |
| Display | none — green text on borrowed CRTs | millions of pixels |
| Job | fly a 2,000-ton spacecraft, never crash | almost everything, may crash |
The asymmetry is the point: the Shuttle’s computers were a thousand times weaker than a musical greeting card is today — and carried 400,000 lines of flight software with a defect rate modern teams still study. Slowness was survivable. Wrongness was not.
April 10, 1981: the very first Shuttle launch stopped at T−20 minutes because the fifth, backup computer refused to listen to the other four. A subtle timing skew — about a 1-in-67 chance on any given power-up — had shifted the primaries’ clock by 40 milliseconds. Young and Crippen climbed out; the world’s most scrutinized software bug got fixed; STS-1 flew two days later. Timing between cooperating computers is exactly what our clock-skew tests probe.
Four primary computers ran in lockstep, comparing answers hundreds of times a second; force-summing hydraulics let the majority physically overpower a wrong actuator command. A sick machine shows a signature you can see in this project’s own five-GPC demo: the healthy majority each point at the failure — and the failed one votes against the world.
The original AP-101B remembered with woven magnetic cores — memory you could hold, bits you could point at. Too small to hold all of a mission’s software at once, so crews reloaded programs from tape between flight phases. The 1990s AP-101S upgrade (the machine emulated here) swapped cores for chips and doubled memory — to one megabyte, roughly a two-second MP3.
This is the part the single-program console can’t show: five emulated AP-101s running at once, exchanging their answers over shared serial buses in the pattern the orbiter’s used. One of them — GPC 2 — has been given a corrupted sensor. Watch it compute 13 where everyone else computes 42, watch the values cross the buses into every machine’s mailboxes, and watch the healthy majority vote it out while the force-voting actuator physically ignores its command.
What you are watching is a reconstruction. The buses, the listen mode, the sync discretes and the timeout behaviour are emulated from IBM’s and Rockwell’s documentation, and they are cited. But the redundancy-management software itself — the code that actually decided which computer to believe — lived in the primary flight software, which is not among the recovered artifacts. This demonstrates the mechanism the orbiter used. It does not run the orbiter’s own voting code, because nobody outside NASA has it.
Force-voted actuator — the hydraulics have the last word
Four command ports, one per computer. The surface follows the majority; a port that keeps disagreeing is physically bypassed.
Because one computer can be wrong without knowing it. A cosmic ray flips a bit; a memory cell fails; a sensor lies — and a single machine will confidently steer you into the ground, because from the inside, a wrong answer feels exactly like a right one. Two computers can detect a disagreement but can’t tell who’s right. Three or more can out-vote the liar. The Shuttle flew four in lockstep — enough to survive one failure and still keep voting after it — plus a fifth running different software entirely, in case the bug was in the software all four shared. You watched the principle above: GPC 2 never knew it was wrong. The vote knew.
In flight: only the five GPCs aboard each orbiter. But most executions happened on the ground. IBM’s Houston teams ran builds nightly in the Software Production Facility at Johnson Space Center; the SAIL (Shuttle Avionics Integration Lab, Houston) flew every mission first on real avionics hardware wired to simulators; crew trainers ran it daily; Owego ran it on test rigs. When the fleet retired in 2011, the machines that could execute this code went to museums — which is why an emulator like this one is now, as far as we know, the only place these instructions still run.
Three real programs, each one traced instruction by instruction. Two things move together: the statement a programmer wrote, and the code the compiler turned it into. Neither mapping is ours — the compiler emitted a table saying which addresses belong to which statement, the linker emitted another saying which routine owns which address, and this panel only reads them.
When the badge turns amber the processor has left the program entirely and is down inside the flight runtime library — NASA’s own code, linked in behind every WRITE. That is where nearly all of the time goes.
Source
Where the processor is
Printer output so far
The routines on this page are pieces of a much larger job. The Shuttle’s primary flight software — about 400,000 lines of HAL/S and assembly — was not one program but a set of them, and the crew switched between them in flight by typing OPS numbers on the keyboard you saw above. Each “operational sequence” loaded the software for one phase of the mission, because a megabyte of memory could not hold the whole flight at once.
Underneath all of it ran the same machinery you have been watching: the computers voting, the crew typing at DEU keyboards, and the runtime library doing the arithmetic. When guidance needed the angle between the orbiter’s nose and its velocity vector, it called a dot product. When it needed a pure heading, it normalized. When it composed one frame of reference into another, it multiplied 3×3 matrices. Those exact routines run again in the table below — not a re-creation, the code itself.
Ambition worth stating plainly: the Shuttle’s complete flight software is not public, and much of it never will be. What survives — the compiler, the assembler, the runtime library, the computer’s own manual — is what this project has resurrected, and it is enough to run real programs on a faithful machine.
The Shuttle’s runtime library survives as original AP-101S assembly — 205 routines, of which 202 assemble today with the genuine flight assembler. These are the 35 verified so far — single- and double-precision, one- and two-argument: each was assembled, linked, and executed on this emulator, and its answer compared against the same function on a modern machine. The “calls” column matters — when SINH runs, the exponential underneath it is the Shuttle’s own EXP; ASINH reaches down through its LOG and its SQRT. The library is running as a library.
| Routine | What it does | Input | Flight answer | Modern | Match |
| SQRT | square root | 2 | 1.4142132 | 1.4142136 | OK |
| EXP | e^x | 1 | 2.7182817 | 2.7182818 | OK |
| LOG | natural log | 2 | 0.69314724 | 0.69314718 | OK |
| TAN | tangent | 0.5 | 0.54630244 | 0.54630249 | OK |
| ATAN | arctangent | 1 | 0.78539813 | 0.78539816 | OK |
| SINH | hyperbolic sine | 1 | 1.1752014 | 1.1752012 | OK |
| COSH | hyperbolic cosine | 1 | 1.5430803 | 1.5430806 | OK |
| TANH | hyperbolic tangent | 1 | 0.76159418 | 0.76159416 | OK |
| ACOS | arccosine | 0.5 | 1.0471973 | 1.0471976 | OK |
| ACOSH | inverse hyperbolic cosine | 2 | 1.3169575 | 1.3169579 | OK |
| ASINH | inverse hyperbolic sine | 1 | 0.88137347 | 0.88137359 | OK |
| ATANH | inverse hyperbolic tangent | 0.5 | 0.54930592 | 0.54930614 | OK |
| EATAN2 | two-argument arctangent | 1, 2 | 0.4636476 | 0.46364761 | OK |
| EMOD | floating remainder | 7, 3 | 1 | 1 | OK |
| EPWRE | x raised to a power | 2, 10 | 1024 | 1024 | OK |
| EPROD | product of an array | [2,3,4] | 24 | 24 | OK |
| ESUM | sum of an array | [1.5,2.5,3] | 7 | 7 | OK |
| EMAX | largest of an array | [3,9,4] | 9 | 9 | OK |
| EMIN | smallest of an array | [3,9,4] | 3 | 3 | OK |
| DSQRT | square root, double precision | 2 | 1.4142136 | 1.4142136 | OK |
| DEXP | e^x, double precision | 1 | 2.7182817 | 2.7182818 | OK |
| DLOG | natural log, double precision | 2 | 0.69314718 | 0.69314718 | OK |
| DSINH | hyperbolic sine, double precision | 1 | 1.1752005 | 1.1752012 | OK |
| DTANH | hyperbolic tangent, double precision | 1 | 0.76159412 | 0.76159416 | OK |
| DACOS | arccosine, double precision | 0.5 | 1.0471973 | 1.0471976 | OK |
| DATANH | inverse hyperbolic tangent, double precision | 0.5 | 0.54930614 | 0.54930614 | OK |
| DMOD | floating remainder, double precision | 7, 3 | 1 | 1 | OK |
| SNCS | sine and cosine together — the orbiter's trigonometry | 0.5 | [0.479425, 0.877583] | [0.479426, 0.877583] | OK |
| VV6 | dot product — the angle between two directions | [1,2,3]·[4,5,6] | 32 | 32 | OK |
| VV10 | unit vector — normalizing a heading | [3,4,0] | [0.6, 0.8, 0] | [0.6, 0.8, 0] | OK |
| VX6 | cross product — the perpendicular, right-hand rule | x̂ × ŷ | [0, 0, 1] | [0, 0, 1] | OK |
| MM12 | 3×3 determinant | diag(2,3,4) | 24 | 24 | OK |
| MM14 | 3×3 matrix inverse — undoing a rotation | diag(2,4,5) | [0.5, 0, 0, 0, 0.25, 0, 0, 0, 0.2] | [0.5, 0, 0, 0, 0.25, 0, 0, 0, 0.2] | OK |
| MM6 | 3×3 matrix multiply — composing rotations | [[1..9]] × 2I | [2, 4, 6, 8, 10, 12, 14, 16, 18] | [2, 4, 6, 8, 10, 12, 14, 16, 18] | OK |
| VV3 | vector subtract | [5,7,9]-[1,2,3] | [4, 5, 6] | [4, 5, 6] | OK |
Differences appear in the seventh decimal place — the limit of the machine’s 24-bit hexadecimal fractions, not an error. Reproduce any row with tools/resurrect.py SQRT:2.0, which finds the routine’s dependencies, writes a driver, assembles it with ASM101S, links it, runs it, and checks the answer.
The code that actually flew
Scalar mathematics is one thing. These three are flight operations — the shapes of computation the orbiter used to know where it was pointing:
| Routine | What it does | Input | Flight answer |
| VV6S3 | vector dot product | [1,2,3] · [4,5,6] | 32 |
| VV10S3 | UNIT VECTOR (normalize) | [3, 4, 0] | [0.6, 0.8, 0] |
| MM6S3 | 3×3 matrix multiply | [[1,2,3],[4,5,6],[7,8,9]] × 2I | 2 4 6 8 10 12 14 16 18 |
| VX6S3 | cross product | x̂ × ŷ | [0, 0, 1] |
| MM14S3 | 3×3 matrix inverse | diag(2, 4, 5) | diag(0.5, 0.25, 0.2) |
That is the complete attitude toolkit: dot for angles, cross for perpendiculars, normalize for headings, multiply to compose rotations, invert to undo them. A dot product gives the angle between where you are pointing and where you want to point; normalizing turns a direction into a pure heading; a 3×3 multiply composes rotations. VV10S3 reaches down through the flight SQRT to do its job — vector code calling library code calling the square root, every layer of it recovered NASA assembly.
This is how astronauts talked to the computers. There was no keyboard on a GPC — the crew typed on Display Electronics Unit keyboards, and every keystroke travelled a serial data bus to whichever computer was driving that screen. The panel below replays a real session on this emulator: each key you see light up was queued in the DEU, polled across the display bus by a bus-control program, and delivered into the GPC’s memory — the numbers under “GPC heard” are read out of that memory, not the keyboard.
CRT — DEU display
Painted by the GPC over the bus. On the orbiter these were green monochrome CRTs; three of them, any of which could be assigned to any computer with the GPC/CRT key.
DPS keyboard — 32 keys
Crew sequences read like commands: OPS 201 PRO selects a major mode; ITEM 36 +12 EXEC sets item 36 to 12.
GPC heard (over the bus)
Run it live in a terminal: cargo run --bin lazap-dps — type on your own keyboard and watch the emulated GPC poll your keystrokes.
These are defects in the flight system itself. Three of the four are the original engineers’ own admissions, printed in the Principles of Operation under headings that read ANOMALY NOTE — documented, shipped, and flown for thirty years. Written the way you would file them today.
Did any of this actually bite in flight? Honestly: there is no public record of a Shuttle mission failing because of these. Two reasons, both worth understanding. First, the flight software was written around them — comparisons used tolerances, block moves avoided the exclusion zone, ON ERROR was not relied on for matrix inversion. Second, and more to the point, this is precisely what four voting computers are for: a fault that corrupts one machine’s arithmetic gets outvoted before it reaches an actuator. These are latent defects in a system engineered on the assumption that latent defects exist. That is the actual lesson — not that the hardware was bad, but that it was known to be imperfect and flown safely anyway.
Items 1 through 3 were open the entire time the Shuttle flew, and are open now. Item 4 is open in any surviving copy of the compiler.
For completeness, this project’s own defects are tracked in the same file. A resurrection that only lists other people’s bugs is not being honest — but ours belong in an appendix, not alongside the flight system’s. Two so far, both fixed. The first was an MVH decrement-order bug that dropped the leading halfword of every block move, caught by a Shuttle physics program and closed with a regression test.
The second is the more instructive one. A linked image shipped with another program’s symbol table — LAZARUS carrying a byte-identical copy of the hello fixture’s. Nothing failed. The emulator reads only the runtime entry points from that file and those were genuinely shared, so every test stayed green while the panel above this one attributed LAZARUS’s instructions to CSECTs that do not exist in it. A project whose entire claim is provenance had a file quietly asserting the wrong provenance. It was rebuilt from LAZARUS’s own object deck, and CI now rejects any symbol table that duplicates another or names a CSECT its object deck never declared.
Getting the right answer was never the hard part. Getting it in time was. The guidance loop ran at 40 Hz — a new answer every 25 milliseconds, forever, with no option to run late.
These times are the compiler’s own. HAL/S-FC carried a table of per-instruction execution times and printed a TIME: figure beside generated code; this emulator now adds up the same numbers as it runs. One caveat, and it is a real one: the compiler printed the values without a unit. Microseconds is the conventional reading for this hardware and is what the frame column assumes, but we have not confirmed it, so treat that column as indicative rather than settled.
| Program | Instructions | Time units | Of one 40 Hz frame |
| HELLO | 6,613 | 10,970 | 44% |
| 176-P physics | 534 | 1,972 | 7.9% |
| LAZARUS | 401 | 1,221 | 4.9% |
| MM14 — 3×3 inverse | 100 | 466 | 1.9% |
| VV10 — unit vector | 80 | 290 | 1.2% |
| SQRT | 38 | 85 | 0.3% |
Read the top row again. Printing eight short lines of text costs close to half a guidance frame — because almost all of it is the character formatting you watched earlier. Inverting a 3×3 matrix, the operation that undoes a rotation, costs about a fiftieth of one. That ratio is the whole argument for why flight software does not print things.
A resurrection is worth what its boundaries are worth. Everything above is real and checked. These are the things this project does not have, stated plainly so nothing on this page is mistaken for more than it is.
The Shuttle’s own flight programs — roughly 400,000 lines of HAL/S and assembly, the OPS sequences described above — have never been publicly released. What runs here is the runtime library those programs called: the mathematics, the character handling, the I/O. Ascent guidance, entry guidance and the digital autopilot are not here. Nothing on this page flies a spacecraft.
The five-computer vote is emulated from documentation, not recovered from NASA. The buses and the mechanism are real; the software that decided which computer to trust went with the flight software.
Execution times are now modelled — taken from the HAL/S-FC compiler’s own EXECUTION_TIMES table, the one that printed TIME: in Shuttle compile listings. What is not settled is the unit: the compiler prints bare numbers. Microseconds is the conventional assumption and the one used below, but this project has not confirmed it against the hardware manual, so every frame figure here carries that caveat.
202 of the 205 recovered runtime routines assemble. Forty have runnable images and thirty-five are checked against modern mathematics on every build. The rest await test harnesses for double-precision and integer arrays. Five more images run but carry no record of the inputs they were built with, so they are listed as unverified rather than counted.
The rebuilt HAL/S-FC compiler and ASM101S assembler are no longer on the machine that ran them; they were built in temporary space that has since been cleared. The compiled artifacts are committed and are what everything here stands on, but nothing can be recompiled without rebuilding the toolchain from source. It is why only one program on this page can be followed line by line.
No AP-101S was available to test against. Correctness here means agreement with IBM’s documentation, with a second independent emulator, and with modern mathematics — not with silicon.
Everything on this page is a program you can run. The emulator is one Rust project; the historical toolchain is Python. No network, no accounts, no cloud — the whole Shuttle computing world fits in a repository — this one.
Start here
git clone https://github.com/keithadler/lazarus-ap.git cd lazarus-ap cargo test # 194 tests cargo run --bin lazap -- roms/hello/hello.fcm
Watch and explore
cargo run --bin lazap-dps # crew station: type at the DPS keyboard, watch the CRT cargo run --bin lazap-set # the five-computer vote, live in your terminal cargo run --bin lazap-set -- --kill 1 # kill a computer and watch the others outvote its silence
Run flight software
cargo run --bin lazap -- roms/hello/hello.fcm # a HAL/S program, byte-identical to the reference echo "42, 3.14" | cargo run --bin lazap -- roms/read_write/read_write.fcm cargo run --bin lazap -- roms/lazarus/LAZARUS.fcm # written for this project, compiled by the real Shuttle compiler
Resurrect a NASA routine
tools/resurrect.py SQRT:2.0 EXP:1.0 EPROD:2,3,4
# finds the routine's dependencies, writes a driver, assembles it with the
# genuine ASM101S, links it, runs it, and checks the answer against math.h
Look inside
cargo run --bin lazap-trace -- roms/lazarus/LAZARUS.fcm # the JSON trace behind this page cargo run --bin lazap-call -- roms/nasa/VV6RUN.fcm --at 11E cargo test # 191 tests: every instruction, the vote, the flight math
This page is a single self-contained file — it runs from a repository, from a laptop, or from GitHub Pages with nothing but a browser.
Intermetrics, founded in 1969 by veterans of MIT’s Instrumentation Laboratory — the Apollo guidance-software team — designed HAL/S for NASA. The name honors that lineage (many trace it to MIT’s J. Halcombe “Hal” Laning, a pioneer of compiled arithmetic), and the language carried Apollo’s hard lessons into the Shuttle era: real-time constructs, vector math, and no room for undefined behavior.
IBM Federal Systems in Owego, New York built the AP-101 hardware; IBM’s Houston group wrote the primary flight software — the team later made famous by the essay “They Write the Right Stuff” for a process so careful its error rate became an industry legend. Jack Garman — the NASA engineer who made the famous “go” call on Apollo 11’s 1202 alarm — later helped run Shuttle software and wrote the definitive account of the STS-1 bug.
Ron Burkey’s Virtual AGC project spent decades recovering spaceflight software — including the HAL/S compiler source and the AP-101S manuals this project is built from. Don Schmidt’s nsts-sim-gpc pioneered AP-101S emulation. Lazarus AP stands on their shoulders: every instruction here cites IBM’s manual, every divergence is cross-checked against their work, and the goal is the most complete resurrection of this machine ever assembled — hardware, languages, toolchain, and now its stories.
Everything on this page is one living system: an AP-101S emulator built from IBM’s manual; the genuine HAL/S compiler and AP-101S assembler, rebuilt and running; a linker written to replace the one piece history didn’t preserve; five machines voting; and the Shuttle’s own runtime mathematics next in line to run again. The aim is simple to say and long to do: the most complete resurrection of the Space Shuttle’s computing world ever assembled.
A program conceived in 2026, compiled by software written for the Space Shuttle in the 1970s, executed faithfully by an emulator reconstructed from the flight computer’s manual — every WRITE crossing the same runtime machinery astronauts’ displays depended on. Four hundred and one instructions to say hello, count to three, and hand back control. The Shuttle did the same thing, three hundred thousand times a second, all the way to orbit.