Apollo Command Module software (Colossus)
or Lunar Module software (Luminary)
was written in a computer language (AGC assembly language)
invented at MIT's Instrumentation/Draper lab. Software whose
source code is in "assembly language" must be processed to turn it
into a binary format ("machine language") understood by the
computer itself. The program that converts the human-written
source code into machine-readable binary code is called an
"assembler". The conversion from source code to machine code
took place prior to loading the software into the AGC, so the
assembly-language code was actually not actually run by the AGC
itself, but rather was processed by ground computers weeks or
months prior to the actual Apollo flights.
(Incidentally, for debugging purposes, the original developers had
a special read-write module which could be programmed from a paper
tape and then plugged into the AGC and used as if it were a core
rope. While this process was apparently not easy, it was
certainly more convenient than manufacturing a core rope.
The assembler produced the data for creating the paper tape.)
Actually, the situation is slightly more-complex than this.
For one thing, in talking about "assembly language" above, I was
using generic programming terminology, not necessarily used by the
AGC development team. In fact, the programs were generally
in a combination of two different programming
languages, intermixed:
In the second place, as the AGC hardware and the developers'
ideas changed over time, so did these programming languages, going
through various stages. In other words, the programming
language itself was not just one thing, but was several different
things over time, although it remained constant throughout all the
manned missions which actually flew.
The original AGC assembler, which turned this mixture of
programming languages into an executable program that could be
stored in core memories and run on the AGC, was called YUL (from "yuletide") because
the projected delivery date of the MOD 1A guidance computer, with
system software, was Christmas, 1959. As time went on, it
had to support all of the different "target" languages I mentioned
above, and Hugh Blair-Smith, the program's author, tells us that
YUL eventually supported the MOD 1A, MOD 1B, MOD 3S, MOD 3C, AGC4
(Block I AGC), and two versions of the final Block II AGC, which
is seven different targets by my count. In real life, YUL was eventually succeeded
by the GAP (General
Assembly Program), but "YUL" sounds much niftier than "GAP"
(which, sorry, sounds like something from Accounting), so we'll
keep calling it "YUL".
There's a pretty extensive AGC
Information
Series document covering YUL and its operation.
And here's a short
excerpt from the same document, describing the punched-card
format, but with the additional enticement of a couple of images
of actual cards.
YUL, by the way, originally ran on the IBM
650, which quickly ran out of capacity, and hence it was ported to
the more-powerful Honeywell 800. Now, I don't have a
Honeywell 800 in my pocket, so I have no way to run YUL, but I can
show you YUL's complete source code, because Hugh has allowed us
to have it scanned. If you demand the absolute highest
visual quality (by which I mean huge, huge files), you can go to our Virtual
AGC Project at archive.org and download the imagery of the
source code in various formats. However, if you're willing
to get much smaller files, which will download much quicker, but
at a slight loss in quality, we've hosted the page images here as
well:
It has been pointed out to me that if this program were for the
Honeywell 800 computer, it should be in the ARGUS language:
i.e., the input language of the Honeywell 800's ARGUS
assembler. However, it is not in ARGUS
language. What's the deal with that? Well, there were
things the AGC developers wished to do that ARGUS did not support,
such as having space characters in symbols, and spreading out the
code for readability purposes. So they invented a new
format, which they called MITIGUS, and YUL is written in
MITIGUS. There was a separate program, a pre-processor,
which converted MITIGUS to ARGUS. Unfortunately, we do not
have this pre-processor, nor an exact list of rules defining the
relationship between MITIGUS and ARGUS, but have been told that
it's pretty straightforward, and hopefully won't affect your
ability to read the program (and certainly not the comments
embedded in the program!) even if you happen to be an expert in
ARGUS.
Before you turn up your nose at this idea of looking at this
code, though, I'd recommend at least looking over the
"Introduction", which contains no actual code, because you may
find yourself amused at the peculiar brand of humor you'll find
there. There's also a
video of Hugh giving a talk about "Pass 0" of the assembler
at the MAPLD '04 conference. The picture above is him
showing the YUL listing to an interested attendee.
The original YUL accepted a complete program (such as Luminary or Colossus) as decks of punch-cards, and seemingly preserved the code in tape libraries; an actual assembly run therefore worked on chunks of code extracted from the tape libraries. The assembler directly outputs binary machine code. There is no linker.
| At this point, you may be
reasonably be wondering why a mere assembler would ever need
to make 10 passes through the source code. Naively,
one would expect a simple assembler to take 2 passes: one to
resolve the values assigned to address labels, and one to
generate the code. However, there is a complication,
in that pseudo-ops like EQUALS (see the assembly-language
manual) allow forward-references to other EQUALS pseudo-ops.
For example, consider the following code fragment: SYMBOL5
EQUALS SYMBOL4
SYMBOL4 EQUALS SYMBOL3 SYMBOL3 EQUALS SYMBOL2 SYMBOL2 EQUALS SYMBOL1 SYMBOL1 EQUALS 42 In this example, the value of SYMBOL1 isn't known until the end of pass 1, the value of SYMBOL2 isn't known until the end of pass 2, and so on. There is no practical limit to the number of passes needed—if symbol resolution is handled in a straightforward way—because it depends on how many constructs like those above appear within the assembly-language source code. Besides, this simple-minded use of multiple passes is eerily reminiscent of certain behaviors of the original YUL assembler, as evidenced by the following amusing quote from Hugh Blair-Smith (YUL's author): "... [the]
observation about assemblies being so long that they
were performed as overnight batch jobs, brings me to a
confession of one thing I wish I had done better, and I
really think I could have at the time. When it became
clear, early in the project, that the number of words in
AGC memory was going to be greater than the number of
words in the assembling machine's (i.e., the Honeywell
800/1800's) memory, I gave up any attempt to retain the
object program in memory and just wrote each patch of
object code on tape. Then there was a "third "pass of
the assembly process which sorted the object code by
what is perhaps the dumbest sort algorithm possible:
running that tape back and forth and writing the object
code in its proper order on another tape. As long as
programs were just a few thousand instructions, this
went like the wind, but the full-size programs of 36000
or so instructions made Pass 3 pretty boring and
frustrating to watch. We did have a hard disk drive from
1965 or 1966, so I could and should have written my
object code onto that and read off the sorted code in a
flash. There wasn't anything like DOS to keep disk files
out of each other's hair, so this effort would have
involved learning and overcoming some risks of data
getting stepped on. And there were always other little
enhancements that had to be done, so it wouldn't have
been easy—but I still wish I'd found a way to get it
done. I guess one thing that decreased the motivation
was that each assembly had to be printed, in about 3 or
4 hours on the noisy 600 line-per-minute printer, so
there wasn't anything the disk could do about assembly
being an overnight batch process. I had no notion, at
the time, of assembling modules separately and then
linking the object modules, and the long and difficult
history of PC linkers suggests that it wouldn't have
been a good idea to try it even if I had thought of it."
This quote was taken from conference transcripts at MIT's Dibner Institute's now-discontinued History of Recent Science and Technology website. |
