What is YUL?

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".

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 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:

Before you turn up your nose at this idea, 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.

What is yaYUL?

Since most people do not have a Honeywell 800 on which to run YUL — and frankly, here at this project we needed to assemble AGC code beginning in 2003, and didn't even have a copy of YUL's program listing until 2016 — I have created a completely new assembler, duplicating the features of the original YUL to the extent I think important, called yaYUL.  In other words, yaYUL is used to convert Luminary or Colossus source code to a binary format usable by the yaAGC emulator.

As I mentioned above, YUL itself would accept and assemble language from 7 different (though related) versions of the AGC.  yaYUL is not so clever as this, and limits itself merely to the variants of Block 1 and Block 2 languages found in the versions of the AGC programs we've been able to get our hands on.  Even though YUL was succeeded by GAP, I don't feel that "yaGAP" has quite the ring to it that "yaYUL" does, so I feel entitled to ignore that fact.

It is important to understand that there is almost no available documentation of how the assembler is supposed to operate—i.e., of the syntax of AGC assembly language.  (Well, the manual for GAP does exist, but I've not seen it yet.)  In the end, most that is known of the syntax of AGC assembly language has been deduced from Luminary and/or Colossus assembly listings and, frankly, some of this syntax is very obscure.  I have written down what I have learned and what I have deduced in the assembly-language manual.  Therefore, yaYUL is not so much an assembler for AGC assembly language (which is fairly nebulous idea), as much as it is a utility which processes existing Luminary and/or Colossus source-code to produce good core-rope images for those specific programs.  But we've had good luck in feeding most AGC programs into it.

Finally, of course,  yaYUL accepts source-code files rather than punch-card decks.  But like YUL, yaYUL directly outputs binary machine code, and there is no linker.

Invoking yaYUL

Running the assembler is very simple.  yaYUL is a command-line program, invoked as follows:

yaYUL [OPTIONS] SourceFile

The binary executable is automatically created if no fatal errors have occurred during assembly.  The binary file has the same name as the input source-code file, but with ".bin" added to the end of the filename.  For example,

yaYUL Luminary131.agc

would produce a file named "Luminary131.agc.bin", which would be directly usable by the yaAGC program.   An annotated program listing (including any error messages) is written to the screen, or may be captured for later viewing:

yaYUL SourceFile >ProgramListing

As of version 20050728 or later, yaYUL also outputs a symbol-table file that can be used in conjunction with yaAGC's "--debug" switch.  This file will have the same name as the source-file, but with ".symtab" suffixed to it.

In the unlikely event that you choose to create and/or modify some AGC assembly language, it is very important to understand that yaYUL requires at least one free word in each memory bank to store the "bugger word" (checksum) for that memory bank.  You can only use 1777 words (octal) out of each 2000-word memory bank.  If you completely fill a memory bank, the yaYUL is going to overwrite the final word of the bank with a bugger word, and you may or may not see an error message.  (Sorry about that.)

Since nobody is likely to be developing much new software for the AGC, yaYUL doesn't need to have very many command-line options.  (Actually, in spite of saying there will be no new AGC software, I do provide a newly-written AGC program in assembly language, for validating the CPU's instruction set, and yaYUL is perfectly adequate for assembling the validation suite.)  Those options are as follows:

This causes the available options to be listed.

(As of 20160824.)  Indicates that Block 1 assembly-language is processed rather than Block 2 assembly-language.  At this writing the only Block 1 source code available is the Solarium 055 program.

Forces creation of the core-rope image file, which is normally bypassed when fatal errors are detected.  (As of 2005-09-05, there are no known bugs left in yaYUL that need this switch as a workaround.)

(20090629 and later.)  Causes creation of an HTML version of the assembly listing.  The top-level HTML filename is the same as SourceFile, except that the .agc filename-extension (if present) is replaced with .html.  An additional HTML file is created for every source file included by the top-level source file, and you can browse to them through links in the top-level file.  Additionally, the HTML is syntax-highlighted, so that it is easy to distinguish basic-language opcodes from interpreter opcodes from line labels, etc.  Finally, the HTML contains hyperlinking from where symbols are used to where they are defined.  It is also possible to add modern annotations to the source code.

(20100220 and later.)  If --html is used, causes bypassing of "## Page ..." to be treated as a regular AGC assembly-language comment.  This may be useful if you are debugging source-code created from a scanned assembly listing, but probably not otherwise.
This sets the maximum number of passes used by the assembler to the number n. The assembler will stop as soon as it can—i.e., it won't necessarily use all of the allowed passes, if it does not need to. For example, you might set n to 10. 

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:


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.

There are some additional options available for certain specialized purposes, which you can view with "yaYUL --help".

Apollo Source-Code Naming

In the case of each of the original Apollo programs provided by this project, the main source-code file will be named MAIN.agc, and will be located in a directory appropriate to that particular program (Luminary131, Colossus249, or whatever).  For example, to assemble the Luminary (rev. 131) source-code I provide, the appropriate steps (in Linux) might be

cd Luminary131
yaYUL MAIN.agc >Luminary131.lst
mv MAIN.agc.bin Luminary131.bin
mv MAIN.agc.symtab Luminary131.symtab

(In MS-Windows, use "rename" rather than "mv" in the last line above.)

AGC4 Assembly Language

For a full explanation of the formatting of assembly-language files, and of available AGC4 assembly-language instructions, refer to the separately-provided assembly-language manual.  Anyone who's determined to write AGC4 assembly-language will probably also need to consult the developer-info page, which covers important supplementary topics such as the relationships between "i/o channels" and hardware peripherals.  For the latter information, however, comments within Luminary/Colossus source code are the definitive references.

Last modified by Ronald Burkey on 2016-09-22.

Virtual AGC is hosted