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

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

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 when I wrote yaYUL, there was almost no available documentation of how the assembler was supposed to operate—i.e., of the syntax of AGC assembly language.  (Well, the manual for GAP does exist, but I'd not seen it.)  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 or source-code libraries from magnetic tape.  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.  See also the "--blk2" switch below.

(As of 20161009.)  Indicates that the assembly target is BLK2.  The topic of "assembly targets" is confusing, and in particular you should note that "--blk2" is not the opposite of "--block1", though the two are indeed mutually exclusive, nor does it comprise all software for the Block 2 AGC.  It's important to understand that the original YUL program had to support an evolving range of AGC computer hardware designs, and roughly corresponding to them, an evolving range of language designs, both in terms of the basic instructions (the assembly language) and the interpreter language.  As such, YUL supported a variety of "target" systems, each with a short alphanumeric designation (such as "BLK2"), with each corresponding more-or-less to a given hardware architecture plus a given software architecture.  However, yaYUL makes no effort to support the same large range of assembly targets as YUL, but merely focuses on those target systems for which we have complete AGC program listings have survived and are available to us now.  The specific targets supported by yaYUL are:
An example of a YUL target not supported by yaYUL is AGC3.

AGC memory-bank "bugger words" are not necessarily unique; sometimes they are, but sometimes they are not, and in that case there are two distinct bugger words which could be added to a memory bank, with the self-test accepting either of these as being valid.  For one of these possible bugger words, the memory-bank's checksum is equal to the bank number, and for the other it is equal to the negative of the bank number.  Normally, when yaYUL adds bugger word to an assembled memory bank, it chooses the one leading to the positive checksum if possible, but uses the one leading to the negative checksum if not.  With the --flip=b switch, where b is the number of a fixed-memory bank, in octal, this behavior is reversed for memory-bank b; in other words, for memory bank b, yaYUL will try to use the bugger word leading to a negative checksum, and will fall back on the one leading to a positive checksum otherwise.  The only known use of this switch is for bank b=7 of the SUNBURST program.  There are notes in the original YUL source code highlighting bank 7 of SUNBURST as a special case, and you are invited to read that source code if interested in this point.

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

(As of 20161009.)  Simply reformat the source file into a normalized form (i.e., with standardized alignment of columns), outputting it on stdout, and then exit.  This does rely on the input file being at least partially formatted correctly, in the sense that labels begin at column 1 and opcodes at column 17.  Either spaces or tabs (interpreted as moving to the next multiple of 8 spaces) can be used in the input but at present, tabs will be converted to spaces in the output.

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

--ascii, --ebcdic, --honeywell
(20210420 and later.)  By default (or with --ebcdic), yaYUL sorts AGC symbol tables in the ordering implied by an EBCDIC character encoding, which matches the ordering of symbol tables produced by the original GAP assembler.  With the --honeywell switch, yaYUL instead sorts according to the character encoding of the Honeywell H-800 computer system, which is the ordering that symbol tables created by the original YUL assembler followed; the AGC programs RETREAD, AURORA, SUNBURST, TRIVIUM, and SOLARIUM should be assembled with the --honeywell switch.  Finally, with the --ascii switch, the native (ASCII) ordering is used; prior to the 20210420 version of yaYUL, ASCII was the only available option.

(20220422 and later.)  Provides reconstruction support in assembly-listing files.  This command-line switch could optionally be used during the engineering process of reconstructing source code, but then should be removed once the reconstructed AGC source code was released.  To understand what that means, the following background info is needed.

For AGC source-code versions which are "reconstructed" rather than transcribed from a contemporary assembly-listing printout — for example, as of this writing, Comanche 44, 45, 45/2, and 51 are all reconstructed versions of COLOSSUS — it is usual to add modern ##-style comments to the reconstructed code at each point where the reconstructed code differs from a baseline version of the code used as a starting point for the reconstruction process.  Each change is documented and justified by an added comment.  For example, Comanche 51 was reconstructed starting from Comanche 55 as a baseline, so each difference between Comanche 51 and 55 is justified by a ##-style comment.  Actually, these justifying comments tend to be sequences of ##-style comments rather than just a single comment line, with the very first line containing the string "Reconstruction:" somewhere within it.

Normally, however, ##-style comments contain HTML tags in addition to plain-text descriptions, because they are really intended to be viewed in HTML versions of the assembly listings.  (See the --html command-line switch above.)  Therefore, ##-comments are not really very suitable for the plain-text assembly-listing files output by yaYUL, and hence most such comments are omitted from the plain-text assembly listings. (Exceptions are page-numbering and file-header ##-comments, which are always included.)  Nevertheless, even though not suitable for normal plain-text assembly listings, the reconstruction ##-style comments can be very useful tools in the plain-text assembly listings during the actual process of reconstructing source code.  What the --reconstruction switch does, therefore, is to add the reconstruction ##-comments into the plain-text assembly listings, while continuing to omit all other ##-comments from them.  The HTML assembly listings are not affected, and always contain all ##-comments, regardless of the use or absence of the --reconstruction switch.

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

(As of 20161009.)  Simply check the syntax and then quit.  This is useful, for example, for checking the accuracy of transcriptions of source code, when only portions of the code rather than the entire AGC program are available.

There may be 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.

This page is available under the Creative Commons No Rights Reserved License
Last modified by Ronald Burkey on 2021-04-22

Virtual AGC is hosted