If you don't already know that the Abort Guidance System is,
perhaps you'll want to continue on to the next section
before before reading this section. But if you do already
know everything there is to know about the AGS, and simply want to
know what we are providing, I'll tell you that we provide
a simulation of the AGS computer (the AEA), a simulation of the
display/keyboard unit for it (the DEDA), and the original
Apollo-era software which can be run on the AEA ... or at least, a
couple of versions of the software. As with the Apollo
Guidance Computer (AGC) proper, you can either run this simulated
AGS in a standalone way, or you can take advantage of the
fact our AGS simulation has been built into the Orbiter spacecraft
simulator via the
project, and in so doing you can fly simulated aborts of
lunar landings or ascents in a much-more realistic way.
Ryan Callaway has made a couple of videos of hypothetical Apollo
12 aborts using the simulated AGS incorporated into NASSP, and
posted them on YouTube. Unfortunately, we only have a couple
of different versions of the original AGS software, known as
"Flight Program 6" (FP6) and "Flight Program 8", and aren't
entirely sure what versions were used for which missions.
However, we believe that something very close to FP6 was used for
Apollo 12, and that's what Ryan uses as well.
The first video illustrates an abort during the lunar descent,
close to the surface; the abort process detaches LM ascent stage
from the LM descent stage, and puts it into lunar orbit in which
the Command Module can later rendezvous with it and dock. Of
course, the computer system is just a black box hidden away
somewhere in the Lunar Module, and isn't visible in these videos,
and the visible representative of the AGS is the display and
keyboard, the DEDA. The DEDA, which is at the lower
right-hand corner of the instrument panel, doesn't appear until
about a minute into the video. The Apollo Guidance
Computer's display/keyboard (the "DSKY") also appears, in the
bottom center of the instrument panel. You'll see that the
abort is a relatively hands-off affair once it gets started, and
it's largely a matter of the DEDA and DSKY both displaying the
"velocity to be gained", with the AGS turning off the engines when
that gets close enough to zero!
This second video is similar, except that the abort takes place on
the lunar surface itself, so I guess you could say it's not even
really an "abort" at all ... it's just using the AGS to control
the ascent rather than using the AGC to do so:
What is the
Abort Guidance System (AGS) or Abort Electronics Assembly (AEA)?
was a computer system used in the LM. It was a completely
separate computer system from the LM's AGC, with a different
architecture, different instruction-set, and different runtime
software. It was in the LM as a kind of backup for the AGC,
but was only supposed to be used (as the name implies) in case of an
aborted lunar descent or ascent. The AGS doesn't have as
commanding a role in the history of lunar explanation as does the
AGC, because no aborts were ever needed in actual missions.
However, when the AGS made its few appearances in history it did so
For example, the AGS was involved in a near-disaster during the
Apollo 10, at the closest approach of the LM to the moon. This
wasn't a flaw in the AGS or its software, of course. It was
caused by problems executing the crew procedures. Recall that the
mission of Apollo 10 was to orbit the moon, then to take the LM
close to the lunar surface (but not to land), and then to jettison
the LM's descent stage and return to orbit with the LM's ascent
stage. When the LM ("Snoopy") staged, the plan was to do
it under AGS/Attitude Hold, with Tom Stafford controlling the
attitude with his hand-controller. As the LM approached the
perilune of the Descent Orbit, at the point of simulated lunar
liftoff, Stafford noticed a small yaw drift (caused, as it turned
out, by yaw rate-gyro stiction) and presumably he wanted to not have
to worry about controlling the LM's attitude when he was punching
off the Descent Stage and firing the down-jets for separation.
Unfortunately the AGS was mistakenly set for "CM pointing," only
useful during rendezvous, so when he toggled back to Auto, from
Attitude Hold, the AGS promptly fired the jets to get the LM facing
the CM in its orbit, above and ahead of them. Because there were no
real attitude rate limits for maneuvering in AGS, the Ascent Stage
swung wildly back and forth as the AGS crudely did its normal thing,
damping out the rates as it approached its target, and settled
nicely where it was "supposed" to be with no inputs from
Stafford. (See the mission
report.) So it all turned out okay.
The AGS was used on the Apollo 11 mission also, when Armstrong
decided not to do the proper attitude sequence as he was getting
ready to re-dock with Columbia after returning from the moon. He
rolled the LM through PGNS gimbal lock, instead of yawing and
pitching, and had to switch to the AGS for attitude control.
Amusingly, the AGS was orginally called the "Backup Guidance System"
but its acronym (BUGS) apparently was not considered suitable.
The AGS was developed by TRW,
rather than by the MIT Instrumention Lab that developed the AGC, so
there was no overlap in development personnel between the AGS and
AGC systems. Furthermore, there was almost no overlap in
engineering technique, other than that both groups of necessity were
generally constrained by the technology available at the time.
For example, both needed to use memory based on core
technology. Moreover, there was no interaction between the AGS
and AGC systems, other than a downlink enabling the AGS to download
the AGC's navigational data (and thus avoiding manual entry of data)
Strictly speaking, the computer part of the AGS is called the Abort
Electronics Assembly (AEA), and so you may sometimes see references
to the AEA rather than the AGS. Various components in
the AGS include:
The AEA—the computer itself.
The Abort Sensor Assembly—a simple inertial measuring system,
strapdown rather than gimballed.
The Data Entry and Display Assembly (DEDA)—similar to the
The AEA can process Rendezvous Radar data but not Landing Radar
data, which makes sense because it's only potential use was to get
away from the immediate vicinity of the lunar surface. There
is, however, a story that Gene Cernan says they had figured out how
to use the AGS to land the LM without an AGC. This may have
been Gene pulling somebody's leg, but I'm gullable enough or
possibly ignorant enough to believe it.
(Thanks to Paul Fjeld for a lot of this explanation and, in fact, a
lot of the verbiage as well.)
A lot of this documentation was digitized by John Pultorak (thanks,
John!) from physical documents preserved and donated by Davis
Peticolas (thanks, Davis!).
Electronic Assembly Programming Reference, H. L.
Stiverson, 7322.3-17, April 1966, 77 pages. This document
is the principle (and almost complete) reference for
understanding the operation of the AEA CPU per se, the AEA assembly
language and assembler, and the operation of the CPU's i/o
ports. There are, however, some confusing aspects to the
Perhaps the most confusing thing is that while the portion
of the document that covers the LEMAP assembler makes it clear
that the integer -1 would be encoded in octal as 0777777 (as
anyone working with a modern PC would expect), the portion of
the document that covers assembly language repeatedly refers
to the octal 0400000 as being "-1". (More specifically,
the reference on these occasions is to "A0 = 1, A1 thru A17 =
0", where A0 is the sign bit and A1-A17 are the data
bits.) In fact, this octal pattern encodes the "largest"
18-bit negative number, namely -131072. (Reader
"spacex15" has pointed out that 0777777 is how the decimal
integer -1 would be encoded, but 0400000 is how the fixed
point number -1.0 would be encoded. That sounds
like the right explanation to me. Kudos!)
Perhaps the most serious omission is that the explanation of
division (the DVP
instruction) in the case where the dividend and/or divisor is
negative is completely lacking and (in the absence of this
explanation) I've never figured out satisfactorily how it is
supposed to work
The known versions of the AGS flight software are as follows.
Unfortunately, we've never found (so far!) any master document that
lists the specific AGS flight-software versions that were used for
particular Apollo missions, or for other purposes, so relating
software versions to missions has required a bit of detective
work! Cooper Lushbaugh has stepped forward to do that work
(thanks, Cooper!), and the details of his work are covered in the Notes
column of the table below. The software dates listed in the Description
column are sometimes the dates in the flight program source code and
sometimes are release dates or other dates mentioned in supporting
Design Mission Computer
All of the other flight programs listed below
(FP2 through FP8) are modifications of this baseline
Flight Program 2
December 1967, probably
Apollo 5 was an unmanned LM Earth-orbit test
Flight Program 3
May 1968, Apollo 9
9 Mission Report (page 9-29) says: "The abort
electronics assembly flight program 3, the inflight
calibration routines, and all input/output interfaces
performed properly throughout the mission."
Regarding Apollo 12: This is less obvious than the
Apollo 11 case, since Apollo 12 was an "H" type mission
rather than a "G" type mission. A couple of
significant FP7 documents weren't released until after
the Apollo 12 mission, so we can conclude that Apollo 12
continued to use FP6. (The documents mentioned are the
FP7 "Programmed Guidance Equations" and "Sim Flight
Operating Procedures. While we don't have the full
texts of these documents as of this writing, the former is
dated December 1969, and the latter's title page can be seen
dated January 1970.) Also, see the following entry
The G&N Dictionaries for the Apollo
12 (page 83) and Apollo
13 (page 101) missions allow us to conclude that
Apollo 12 and 13 used different versions of the AGS Flight
Program. The AGS portions of these "dictionaries"
relevant to our discussion are basically lists of AGS memory
locations, including descriptions and the allowed values
they can contain. Since the dictionaries for Apollo 12
and 13 differ slightly, the AGS software versions must
differ as well. An example is addresses 225/226. Since
Apollo 12 (see preceding entry in this table) used FP6, then
we'd conclude that Apollo 13 used a later version of the
Just as we can conclude that Apollo 12 and 13 used different
versions of the software, we can conclude that Apollo 13 and
14 used the same version. We can do this by comparing
the Apollo 13 G&N Dictionary described above with
PGNS/AGS Training Card", because the training card
also contains a list of AGS memory addresses, and that list
agrees with the Apollo 13 dictionary. But beyond that,
the training card specifically states that it covers:
AGC software Luminary 178 (which was used in the
Apollo 14 LM)
AGC Flight Program 7
A summary of all that is:
Apollo 14 used AGS Flight Program 7
Apollo 13 used the same AGS Flight Program as Apollo
Apollo 13 used different AGS software than Apollo 12,
which is known to have used Flight program 6.
The conclusion that both Apollo 13 and 14 used FP7 is
By the way, it's tempting to say that it doesn't really
matter for Apollo 13 which flight program version was
used, since because of the service-module explosion there
was no lunar landing. But in fact, the
AGS was in fact used in Apollo 13 for a manual
course correction. My reading of the linked
flight log is that the AGS/DEDA was only used in the
course correction to monitor velocity (AGS address
470). But this was identical in FP6 and FP8, and
therefore presumably in FP7. In other words, even
though we presently have no copy of FP7, either FP6 or FP8
might suffice in a simulation of an Apollo 13 mission.
While we have no program
listing of FP7, it may be worth considering that the AGS
section of the Apollo
13 G&N Data Dictionary, when combined with the
FP7-to-FP8 change notes in the FP8
operating manual, might provide some basis for
reconstructing FP7 source code from FP6 & FP8 source
Flight Program 8
Released April 28, 1971 (copy
is dated December 18, 1970), Apollo 15-17.
the Abort Electronics Assembly (AEA)
"As with the PGNCS computer, the
AGS computer went through an evolutionary period in
which designers clarified and settled the
requirements. The first design for the system did not
include a true computer at all but rather a
"programmer," a fairly straightforward sequencer of
about 2,000 words fixed memory, which did not have
navigation functions. Its job was simply to abort the
LEM to a "clear" lunar orbit (one that would be higher
than any mountain ranges) at which point the crew
would wait for rescue from the CM, with its more
sophisticated navigation and maneuvering system. The
requirements changed in the fall of 1964. To, provide
more autonomy and safety, the AGS had to provide
rendezvous capability without outside sources of
information. TRW, the
contractor, then decided to include a computer of
about 4,000 words memory. The company considered an
existing Univector accumulation machine but, instead,
chose a custom designed computer.
"The computer built for the AGS
was the MARCO 4418 (for Man Rated Computer). ... The
computer was 5 by 8 by 23.75 inches, weighed 32.7
pounds, and required 90 watts. The memory was bit serial access,
which made it slower than the PGNCS computer, and it
was divided into 2K of fixed cores and 2K of erasable
cores. The actual cores
used in the fixed and erasable portions were of the
same construction, unlike those in the PGNCS computer.
Therefore, the ratio of fixed memory to erasable in
the MARCO 4418 was variable. TRW was obviously thinking in terms of
adaptability to later applications."
The AEA (the
computer) had the following characteristics:
10000 (octal) words of memory. The lower 4000 (octal)
words were "temporary" memory, while the upper 4000 (octal)
words were "permanent" memory. These two banks differed in
that an "inhibit" signal was omitted in the upper bank, so that
the contents could not be altered by the running program.
The memory-cycle time is 5 μs.
Memory words were 18 bits. Instructions used 5 bits as
an operation code, 12 bits as an address, and 1 bit to indicate
whether or not the address was indexed. (For an indexed
instruction, the address was altered when the instruction was
executed by adding the contents of a dedicated index
Data words were 2's complement. In the case of many
calculations, a fixed-point discipline was used, so that
fractional values could be used. This method is similar
using a slide rule—a paradigm naturally quite familiar to the
programmers of that time. (A slide rule represents only
numbers in the range 0 to 1 and the user is supposed to mentally
track the position of the decimal point for each successive
multiplication or division he or she performs.)
There were several dedicated registers, outside of the
memory-address space. Some of them, like the M register depicted in
the diagram at right, aren't of real interest to the programmer,
since they function at the hardware level, transparently to the
program. The registers of interest to the programmer are:
The "accumulator", involved
implicitly in most instructions as the source or
destination for data.
The "multiplier quotient"
register. A kind of less-significant-word register
for extending the length of the accumulator, but also used
in a dedicated way for a number of different kinds of
operations like multiplication and division.
A three-bit register which
can optionally be added to addresses to create an indexed
addressing mode by setting the index flag in the
instruction word. Also used as a loop counter.
Obviously, since the register can only take values 0-7,
the array and loop sizes used were very small.
I/O space. There was an i/o address space, separate
from the memory address space, by which peripheral devices
were accessed by dedicated instructions. These i/o
ports were used for such things as accessing the DEDA (Data
Entry and Display Assembly), reading gimbal angles,
controlling the engine, telemetry downlink, and so
forth. Only a handful of i/o ports were needed, but
these were spread out over the 12-bit i/o address space.
There were 27 different types of instructions, each
requiring one word of memory. Execution times ranging
from 10 μs to 104 μs, but most were in the 10-16 μs
range. Multiplication and division required 70-73 μs.
yaAGS is the program which
emulates the AGS CPU. In other words, it loads the binary form
of the AGS flight software, or other software newly written for
verification purposes, and then executes that software on a cycle by
cycle basis, emulating the CPU's architecture and instruction
The program has just become operational (2005-06-15), but probably
with plenty of bugs to fix.
Of itself, the emulation is not very visually exciting, since the
CPU requires peripheral devices as well. The peripherals are
not provided directly by yaAGS;
rather, they must be emulated by separately-provided software.
(Once these peripherals are available for yaAGC, we'll work to make them available for yaAGS as well.) This
technique allows a developer of (for example) a lunar lander
simulation to use the CPU emulation, but to replace simulated
peripherals in order to achieve better integration. The
principal peripheral is the DEDA (see below).
The command-line syntax is:
yaAGS [OPTIONS] --core=Filename
The name of the file for the
"--core" switch is an executable binary created using the yaLEMAP cross-assembler or
utility. (Typically, "--core=FP6.bin" or "--core=FP8.bin",
since these are the available AEA flight binaries.) Both
programs are described below. The core file format is
discussed in the binLEMAP
section, although it won't be of interest to most users.
The presently-defined options are:
Displays a list of options
(such as this one) and then quits.
Causes the AGS program (such as
Flight Program 6 or Flight Program 8) to halt prior to
executing its first instruction, and activates a debugging
mode (very primitive) in which you can do things like examine
AEA CPU registers, single-step through the AGS program,
etc. This mode is described further below.
(20090319 and later.)
Prints messages on the console about data packets received
from the DEDA(s).
yaDEDA, the AGS
The term DEDA refers to the Data Entry and Display
Assembly, which is the assembly used by the astronauts to enter
data into the AGS, or to see data displayed by the AGS.
The DEDA was mounted in the lower-right portion of the LM's
control panel, just in front of the LMP (Lunar Module
Pilot). Recall that in the somewhat odd terminology
employed in the Apollo program, the LMP did not actually pilot
the LM. Rather, the commander piloted the LM from the
yaDEDA is an emulation
of the DEDA for use with yaAGS.
it is certainly possible for the developer of a LM simulation to
develop his or her own emulation of the DEDA. Indeed, the
program yaDEDA2 has now
superceded the original yaDEDA
program, although the original is still available if someone was
interested in it. When I refer to "yaDEDA" below, I
actually mean to refer interchangeably to both "yaDEDA" and
"yaDEDA2" unless I state otherwise. For information on
developing these kinds of alternative implementations, you
should refer to the developer info
page. You'll notice that the screenshot of yaDEDA to the right is
somewhat different from the drawing of the DEDA above,
particularly as to the HOLD-key; that's because of discrepancies
in the available documentation, so feedback on this issue is
Unlike the DSKY, which is basically completely useless without
the AGC, the DEDA has some built-in smarts. Actually, most
of the DEDA user-interface is built into the DEDA, and so yaDEDA can be operated even
without the presence of yaAGS.
that the DEDA has two displays: a three-digit display
which is an octal "address", and a 5-digit display (plus sign)
of "data". Quite a lot of the operation of the DEDA was
simply to enter an address (in the first 512 bytes of AEA
memory), after which the AEA would output the value of that
memory location every half-second. The AEA software would
format the data, which could be either octal or decimal, or
could involve various scale factors or units. However, the
units and scaling and octal vs. decimal choices are hardcoded
into the AEA software, and are not selectable by the user.
This mode persists until pressing the HOLD key, which signals
the AEA software to stop outputting data. (After hitting
HOLD, you could hit READOUT again to restart the
data-monitoring.) To put the DEDA/AEA in this continuous
readout mode, you do the following on the DEDA keypad:
CLR OctalDigitOctalDigitOctalDigit READOUT
The digits appear on the address display as you enter
them. Any error in entering this sequence causes the
OPR ERR lamp to light, making the DEDA basically inoperative
until the CLR key is pressed again. All of this,
except for the actual generation of the data, occurs within
the DEDA without needing an AEA (yaAGS).
The other thing you can do with the DEDA user interface is
to perform data entry: i.e., to send the AEA a command
or data. The interpretation of the data you enter is
dependent on the address you enter:
Again, both the 3-octal-digit address and the 5-digit data (plus
sign) appear on the display as you strike the keys, but any
departure from the above sequence lights the OPR ERR lamp, which
can only be cleared with CLR. The 5-digit data can be
either octal or decimal, but this is address-dependent (as
hardcoded into the AEA software), so it's not a matter of your
choice. Other than the actions which this type of
operation is supposed to cause within the AEA, all of this takes
place within yaDEDA.
The command-line syntax for the yaDEDA2 or yaDEDA
yaDEDA2 [OPTIONS] or
The presently-defined options
Display a list of options,
something like the information shown here.
yaDEDA and yaAGS are a client/server pair, and can be
running on the same computer or on different computers. In
order to connect to the yaAGS
has to know the IP-address of the machine on which yaAGS is running. By
default this is "localhost"---i.e., the two are running on
the same computer. However, a different IP address may be
specified using this command-line switch. In Linux, this
may be either the machine's name, or else a numerical
address in dotted format (n.n.n.n). MS-Windows---at least
Windows 98---is somewhat crippled in this respect, and
will only accept a host name rather than a numerical IP
Similarly (see above), in
addition to an IP address, a port number is needed. This
must be in the range of port numbers yaAGS is scanning
(which by default is 19897-19906). If no port is
will use 19897, in accordance with the suggested port
assignments on the developer
interface is simply too big for PCs with lower graphical
resolution (smaller than 1024×768). If the
--half-size switch is used, half-size graphics are used,
and so the interface should be usable even down to 640×480
resolutions. The smaller interface doesn't really
look very good, because it is simply blindly scaled down
from the larger interface, rather than being optimized,
but at least it's usable at 800×600 and 640×480
Adds a delay at start-up,
so that yaDEDA
does not immediately begin attempting to communicate with
current defaults are 0 ms. in Linux and 500 ms. in
Win32. This "feature" has been added as a temporary
work-around for problem report
#23, and probably has no other sensible purpose.
Even on Win32 it isn't usually needed, but it's here for
the 10% (or whatever) of the time it's needed.
(Final version of yaDEDA only; not
available on yaDEDA2.)
the locations of graphics files used by the yaDEDA program to the
./pixmaps/yaDEDA/ folder rather than the default system
folders. This makes the program compatible with the
directory structures and runtime assumptions of the VirtualAGC GUI system
rather than the previously used script-driven runtime
yaLEMAP, the AGS
The original cross-assembler for AGS assembly language was known as
the "LEM Assembly Program", or LEMAP.
can read all about it in the document by H. L. Stiverson (see
above). We don't have the code for the original
cross-assembler, nor (if we did) do most of you have access to the
type of computer on which it ran. So, we're providing you with
a completely new assembler that can assemble the original
flight-software source code into a binary usable by the AGS CPU
Naturally, we call this new cross-assembler yaLEMAP.
The command-line syntax for yaLEMAP
yaLEMAP [OPTIONS] SourceFilename
The only presently-defined option is:
This switch causes the assembler to
load the binary file called Filename,
and to compare the binary output produced by assembly of the
source code to the contents of Filename.
Filename was produced by
an earlier run of yaLEMAP
or binLEMAP (see
below). This is type of comparison is useful principally for
regression testing of the assembler itself, and (indeed) such
regression testing is performed during a normal build. This
switch also causes a change in yaLEMAP's
codes, which are normally based on the presence of errors and
warnings. (In other words, a non-zero return code normally
occurs in case there are errors during assembly.) With the
"--compare" switch, though, yaLEMAP
has a return code of zero when the binaries match, and a non-zero
return code when they don't match. Naturally, one could use
operating-system utilities (such as fc in Win32 or diff
in Linux) to mimic this functionality as well; however, the
"--compare" switch also has the property of adding meaningful
messages about any mismatches to the assembly listing, which the
operating-system utilities do not.
(20090629 and later.) Causes
creation of an HTML version of the assembly listing. The
HTML filename is the same as SourceFile,
except that the .ags filename extension (if present) is replaced
with .html. The HTML is syntax-highlighted, so that it is
easy to distinguish 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 define modern annotations for the source
yaLEMAP is a simpler program
in may ways than the AGC cross-assembler yaYUL. There are several reasons for this:
The architecture, and particularly the memory-map of the AGS
is much more regular than that of the AGC.
The AGC assembler has to worry about assembling several
different kinds of languages in the same source file: AGC
assembly language, AGC interpretive language, telemetry downlink
language, and perhaps others I've forgotten about. The AGS
assembler only has to worry about AGS assembly language.
The AGS flight programs are so much shorter than AGC flight
programs -- about ten times shorter, in fact. Therefore, a
complete AGS flight program can be conveniently provided in a
single source file, rather than having to break it up into 30 or
40 shorter files as is done with the AGC flight programs.
yaLEMAP always outputs its
binary in a file called yaLEMAP.bin, which has a format compatible
with both yaAGS (see above)
and binLEMAP (see
below). Similarly, the assembly listing file is always output
to the file yaLEMAP.lst. The listing format is not identical
to that of the original LEMAP
program, but its flavor is pretty similar, and the changes are
probably more in line with today's thinking. (For example, in
the symbol tables produced by yaLEMAP,
the symbols are referenced to their numerical values. In
symbol tables produced by LEMAP,
the symbols are referenced to line numbers within the assembly
listing, and you can look at that line number to see the numerical
value which has been assigned. That's logical, perhaps, in a
world where everybody is looking at paper printouts; it's not
logical in an online world, so I haven't felt too bad about changing
The syntax of the source code for yaLEMAP
similarly isn't identical to that accepted by LEMAP as outlined in the AGS
programmer's manual, but it's pretty close. The
principal differences are:
yaLEMAP is not
column-dependent the way LEMAP
is, except that labels are still expected to begin in column 1.
Comments in yaLEMAP
are expected to begin with the symbol '#'. Anything
following the '#' symbol to the end of a line is ignored.
binLEMAP, for ASCII Entry of AGS Executable Binary
There are two distinct ways of obtaining executable AGS binaries
from an AGS assembly listing. You could enter the
assembly-language instructions into the computer, creating source
code that can be assembled with yaLEMAP
as explained above. Or, you could enter the octal form of the
opcodes into the computer, creating a file of numbers that can be
processed with the binLEMAP
utility. In fact, for verification purposes we do both, and
then compare the results as explained below.
Use of the binLEMAP utility
is quite simple, as it has no command-line options. It simply
reads the standard input and creates a file called
binLEMAP.bin. The command-line syntax is:
binLEMAP < InputFile
The output file, binLEMAP.bin, consists of 10000 (octal)
entries, each one of which is a 32-bit unsigned integer in
little-endian format (i.e. with the least-significant byte
first). The first entry represents AGS memory address 0,
the second represents AGS memory address 1, and so forth.
This file is therefore always exactly 16384 (decimal) bytes in
The input file obeys the following simple rules, tailored to
match the way the assembled data appears in LEMAP assembly listings, in
order to make data entry easy:
Anything following the '#' character is treated as a
comment and is discarded.
All appearances of the character 'p' are removed and
replaced by blank spaces.
Blank lines (after removal of comments and extraneous
white space) are discarded.
A line of the form "ORG OctalValue"
resets the location counter (which starts at 0) to the
A line consisting of an octal number is stored at the
location counter, which is then incremented.
A line consisting of three octal numbers is processed to a
single octal number, which is stored at the location
counter, which is then incremented. (The three values
are treated as a 6-bit opcode, a 1-bit index flag, and a
12-bit address. The opcode and index flag are
logically ORred, the result is shifted upward 12 bits, and
then logically ORred with the address.)
The purpose of the rather odd rule about removal of the
character 'p' is that it means an optional 'p' can be inserted
after an octal number. It helps me in my proofing to run
these files through the text-to-speech converter on an iMac, and
this subterfuge of adding the extra 'p' fools the iMac's
text-to-speech converter into pronouncing the numbers in the way
The following versions of AGS flight software are available:
Flight Program 6 (FP6), June 1969. This was used in the
Apollo 11 mission. The source code and binary are
available and believed to be 100% complete and accurate.
Flight Program 8 (FP8), December 1970. Fabrizio
Bernardini tells us that according to the A17 Flight Readiness
Review documentation, that the software was released April 28,
1971 ... and of course, the fact that it was specified implies
that it was used for Apollo 17. From the release date, we
conclude that it could not have flown before Apollo 15.
Thus, we assume it was used for Apollo 15-17. The source
code and binary are available, and are believed to be 100%
complete and correct.
If you know of other existing versions of the AGS source code, give
them to us!
Validation of the AGS source code is somewhat streamlined from the
method used to validate AGC source code. The following process
The source code is entered into the computer from the assembly
It is assembled with the yaLEMAP
cross-assembler. As a byproduct, a ASCII file is produced
with just the columns of the assembly listing containing the
assembled octal values.
The byproduct ASCII file mentioned above is fed into a
text-to-speech converter program, and the now-audible octal
codes are compared visually against the original scan of the
assembly listing. The source files are fixed as needed
when mismatches are found.
Obviously, it's a matter of opinion how many times the
proofing process described above needs to be repeated. I have
repeated it only until the embedded checksums are correct. If
anyone wants to volunteer to perform additional proofing—for
example, of the program comments, which are not checked by the
process I used—feel free to do so and to report the results to me.
of Flight Program 6
Unfortunately, the assembly listing we have of Flight Program 6 is
missing a couple of pages (namely, pp. 90 and 96). From
comparison of FP6 and FP8, I believe that the missing pages contain
code that has not changed between FP6 and FP8, and therefore have
simply substituted the corresponding chunks of code from FP8 into
FP6. The types of circumstantial evidence that this is
acceptable are as follows:
The code preceding and following the missing chunks is the
same in FP6 and FP8.
The line-count of the missing chunks matches in FP6 and
FP8. (37 lines are missing in both cases.)
The lengths of the address ranges of the missing chunks match
in FP6 and FP8. (Actually, the addresses themselves match
rather than merely the lengths of the ranges. In other
words, this entire section of code assembles not just to the
same binaries in FP6 and FP8, but literally to the same memory
addresses. That's stability for you!)
The assembly listings contain both symbol tables (giving the
value of each symbol) and symbol-usage tables (listing all the
lines of code where each symbol is used). I have not yet
compared the symbol tables for FP6 and FP8 in the appropriate
address ranges, since it is very involved and I am busy.
(If you want to volunteer to do this, contact me!)
As explained earlier, the checksums need to be correct.
And indeed, they are
correct. Actually, it turns out that the checksum for the
address range 4000-7777 (octal), which contains these missing
pages, is identical for FP6 and FP8, leading us to believe that
this entire memory block has not changed at all.
Finally, if you refer
to page 72 of the TRW
LM/AGS Design Survey document, you'll find the following
explanation: "The equations programmed into the hardwired
portion of the memory are identical in all flight
computers (except for a few early prototype computers used for
test purposes). The equations programmed into the
softwired portion of the memory are subject to change from
mission to mission." The hardwired portion of the program
is, of course, the address range 4000-7777. On p. 30 of
the same document, you'll find the additional explanation that
the hardwired portion of the program is designated "HO3", but
that the earlier versions (for the "early prototype computers")
were designated "HO1" and "HO2". Consequently,
invariance of the hardwired portion of the program is a design
feature rather than an accidental characteristic.
This all seems pretty conclusive, but if you have a listing of FP6, please
scan pages 90 and 96 and send them to me and save us this dreadful
uncertainty! (Of course, if you have other versions of the
program, scan them and send them to me too! Or send them to me
via snail-mail, and I'll scan them and return them.)
yaAGS Debugging Mode (--debug)
The description that follows
covers the "classic" debugging mode for versions prior to
20090427. I retain this description as-is for the
benefit of those using one of those versions of yaAGS. However,
for versions 20090427 and later, command-line debugging is
in the process of changing to a style more closely related
to that of the widely used gdb program, and the "classic" mode
described below will gradually disappear. Since
these changes have been driven by Onno Hommes, we have
agreed that Onno will maintain documentation for the new
debugging mode at his website.
When the "--debug" command-line switch is used, a mode is entered in
which AGS programs can be debugged. This mode is very
primitive compared (for example) to the facilities provided by a
debugging program like gdb,
but has been pretty useful for my purposes, and may conceivably be
useful for yours. You are unlikely to find this mode (or my
description of the mode!) of any use unless you are very familiar
with AGS assembly language, and are writing/debugging AGS
code. In this mode, rather than simply running the software
contained within the core image, yaAGS
halts prior to executing the first instruction of the program and
allows you to interactively determine its further actions. You
are presented with a status message and a prompt from which you can
The debugging mode's status display may look something like this:
Stopped because program loaded. A=000000
Icount=1 Cycles=0 6000
706177 DLY 6177 >
We see the current values (in octal) of various important CPU
registers. All numerical values displayed by the debugger are
in octal, because octal notation is used almost exclusively
throughout existing AGS code, and because almost all of the
numerical values reported by the LEMAP
assembler were in octal. The values shown are for:
The A(ccumulator) register.
The Q(uotient) register.
The Overflow flag.
The Index register.
Whether the CPU is halted (by the DLY instruction) until the
next 20 ms. signal.
The number of times (in decimal) that this particular type of
CPU instruction has been executed.
How many cycles (of 0.9765625 microseconds each) have elapsed
since the program started.
The final status line is, of course, a disassembly of the next
instruction scheduled to be executed. It shows the current
address (6000), the
octal value of the instruction (706177), and a disassembly of that octal value
into assembly-language (DLY
6177). The debugging mode does not currently
understand any labels defined within the AGS program itself;
therefore, understanding code like "DLY 6177" as something like "DLY INIT" (involving
labels) is aided by having a symbol table or assembly listing at
The debugger understands addresses in one of three formats:
Addresses within memory are represented by a single octal
number, such as 1234. Modifiable memory is in the range
0000-3777, while non-modifiable memory is in the range
Addresses within input-channel space (i.e., accessed by the INP instruction) are
prefixed by 'I', such as I2020.
Addresses within output-channel space (i.e., accessed by the OUT instruction) are
prefixed by 'O', such as O2020. There is also a fictional
output register O0, which is used by yaAGS to combine all of the discrete
outputs. The bit positions within O0 correspond to the AEA
CPU's discrete outputs as follows:
0001 Ripple Carry
0002 Altitude discrete
0004 Altitude Rate discrete
0010 DEDA Shift In discrete
0020 DEDA Shift Out discrete
0040 GSE Discrete 4
0100 GSE Discrete 5
0200 GSE Discrete 6
0400 Test Mode Failure discrete
1000 Engine Off discrete
2000 Engine On discrete
Within the status display's instruction-disassembly, the distinction
between memory locations and i/o channels is always obvious, so i/o
channel numbers are not prefixed by 'I' or 'O' in disassemblies.
The user-commands which are currently recognized by the debugger
string beginning with the character '#' in the first column) is
a comment, which is discarded without a warning message.
This is principally useful for writing scripts (which has not
yet been implemented).
BREAK A—defines a
new breakpoint at memory-address A. The program will halt upon
encountering an instruction at the address of the breakpoint.
BREAKPOINTS—displays all currently-defined breakpoints and
CONT—begin running the program. The program will simply
run until encountering a breakpoint.
CONT-TIL-NEW—same, but also stop if an instruction-type not
previously encountered in this session is hit. (Only good,
obviously, for debugging the simulation.)
DELETE—without an address, DELETE simply deletes all existing
breakpoints and watchpoints.
DELETE A—deletes the
breakpoint or watchpoint (if any) currently defined at address A. The address should
be prefixed with 'I' or 'O' for i/o channel addresses.
DUMP—without arguments (i.e, no N and no A),
dump is performed using the last N and A
DUMP [N] A—displays the current
contents of N
successive memory locations or i/o channels, starting at address
A. The formats
allowed in A are
described above. N
is shown in brackets to indicate that it is optional. If N is omitted, it defaults
to 1. Since no i/o channels are at consecutive addresses,
no N option is allowed
for i/o-channel addresses.
QUIT or EXIT—exits yaAGS.
STEP [N] or NEXT [N]—executes the next N assembly-language
instructions. If N
is omitted, then it defaults to 1. Notes that this command
can be abbreviated as 'S' or as 'N'.
WATCH A—defines a
new watchpoint at erasable-memory address A (using one of the address
formats described above). The program will halt after executing an
instruction that changes the value stored at the address of the
EDIT A V—stores the
octal value V at the
adress A. The
formats allowed in A
are described above. Unlike the other commands above, this
command supports the fictitious "output" addresses like 2410
which set or reset a discrete output. Note also that for
output-channel addresses, appropriate instruction packets
associated with the output channels are transmitted to
peripheral devices. Instead of an address, you can also
access the CPU's internal registers using one of the following
for A. (Note
that "EDIT PC" only changes the program counter, and not the
complete CPU state, so it's better to use the BACKTRACE command
BACKTRACES—displays the most recent (50) backtrace points
(i.e., points at which the program branched).
state of the system (CPU, memory, i/o channels) to backtrace
point #N (from the
list displayed by the BACKTRACES command).
instructions starting at address A. By default A is the current
address of the program counter and N is its prior value (starting at 24 when
the program starts).
COUNTS—displays a list of the number of times each type of
AEA instruction has been executed. The numbers are in
PATTERN V M—sets
a "pattern" with value V
and mask M.
A pattern is similar to a breakpoint, except that it uses
the instruction code rather than the program counter.
In other words, execution is halted upon finding that the
instruction code is equal to the value V. The
instruction code is logically bitwise-ANDed with the mask M prior to the
comparison, so that only selected fields in the instruction
code are really used.