chrislgarry/Apollo-11 保存了 Apollo 11 导航计算机的源代码转录。这里不是纪念性质的代码仿写,而是从 MIT Museum 保存的纸质程序清单数字化而来的 AGC 源码,包括指令舱使用的 Comanche055 和登月舱使用的 Luminary099。
第一次打开仓库时,最容易困惑的地方是:为什么没有熟悉的 src、构建脚本和应用入口?答案是,这套软件来自 1969 年,其组织方式、汇编工具和硬件模型都早于现代软件工程习惯。本文从目录入手,给出一条能够实际读下去的路线。
快速答案
先克隆源码:
|
|
然后根据飞船模块选择目录:
Comanche055/:指令舱 Command Module 的 Colossus 2A 程序;Luminary099/:登月舱 Lunar Module 的 Luminary 1A 程序。
建议不要从头逐行阅读。先打开各目录的 README.md 和 MAIN.agc,再按任务查看 ALARM_AND_ABORT.agc、EXECUTIVE.agc、DISPLAY_INTERFACE_ROUTINES.agc 等模块。若要编译或模拟运行,应转向 Virtual AGC,Apollo-11 仓库本身主要承担历史源码保存和校对工作。
这个仓库保存了什么
Apollo Guidance Computer,简称 AGC,是 Apollo 飞船制导、导航和控制系统的重要组成部分。Apollo 11 的指令舱和登月舱任务不同,因此使用两套程序:
| 目录 | 对应程序 | 用途 |
|---|---|---|
Comanche055 |
Colossus 2A / Comanche revision 055 | 指令舱导航、姿态控制、轨道计算和再入等任务 |
Luminary099 |
Luminary 1A / LMY99 | 登月舱下降、着陆、上升和交会等任务 |
仓库说明记录的装配日期分别是 1969 年 4 月 1 日和 1969 年 7 月 14 日。源码由 Virtual AGC 社区和 MIT Museum 相关人员根据纸质清单扫描件转录、整理,并持续接受对照原始扫描件的校正。
这意味着仓库的主要目标是忠实保存历史材料,而不是把程序重构成现代代码。看到拼写、注释格式或不熟悉的模块边界时,不宜直接按今天的编码规范去“修复”。
为什么源代码被拆成大量 .agc 文件
原始程序是整体装配的单体代码。当时没有今天常见的编译、链接流程,程序模块更接近一叠叠按顺序组合的穿孔卡片。数字化项目为了方便管理,才把庞大的源码拆成多个 .agc 文件,再通过包含关系还原整体顺序。
因此,这里的文件拆分代表自然的子程序边界,但不等同于现代项目中的独立编译单元。每个目录的 README.md 都提供 Source Code Index,把文件与原始打印清单页码对应起来。阅读时应把它当作目录索引,而不是普通项目说明。
AGC 原有的 YUL 和后来的 GAP 汇编器已经无法直接取得。Virtual AGC 项目提供的 yaYUL 使用略有不同的输入格式,仓库中的转录源码也为 yaYUL 做了适配。
推荐的阅读顺序
1. 先看合同、装配信息和入口
从下面三个文件开始,可以先建立程序全貌:
|
|
CONTRACT_AND_APPROVALS.agc 保留项目身份、合同和审批信息。ASSEMBLY_AND_OPERATION_INFORMATION.agc 说明装配结构与子程序调用。MAIN.agc 则把多个源码片段按顺序纳入完整程序。
2. 再看任务含义明确的模块
相比直接研究指令集,先选择文件名能够说明用途的模块更容易进入状态:
|
|
其中 EXECUTIVE.agc 和 WAITLIST.agc 有助于理解任务调度;PINBALL_GAME_BUTTONS_AND_LIGHTS.agc 与宇航员使用的显示和键盘界面有关;告警与重启模块则能看到系统如何处理异常状态。
3. 最后进入具体飞行阶段
指令舱目录包含轨道积分、自动机动、再入控制和姿态控制等程序。登月舱目录更适合从下降制导、着陆阶段、数字自动驾驶和上升程序等任务切入。
文件名中的 Pxx 通常对应宇航员通过 DSKY 选择的程序编号,例如仓库中可以看到 P40-P47.agc、P51-P53.agc 等文件。Rxx 则常用于例程编号。阅读这些文件前,先了解对应飞行阶段和操作流程,会比单独翻译汇编指令有效得多。
在本地快速定位代码
仓库文件很多,使用文本搜索比逐个点击更方便。在 Git Bash、Linux 或 macOS 中可以运行:
|
|
安装了 ripgrep 时,可以使用更快的搜索方式:
|
|
第二条命令可用于寻找著名的 1201、1202 程序告警相关位置,但不要仅凭一次字符串匹配就断定完整触发逻辑。告警编号、产生条件、任务调度和显示过程可能分散在多个模块中,需要结合调用关系阅读。
在 PowerShell 中可以这样列出源码:
|
|
.agc 文件应该怎么看
AGC 汇编与今天常见的 x86 或 ARM 汇编差异很大。面对一行代码时,可以依次识别以下部分:
- 标签:为程序入口或数据位置命名;
- 操作码:AGC 指令或解释器指令;
- 操作数:地址、常量或符号;
- 注释:解释算法、飞行条件和工程限制;
- 页码标记:帮助与原始纸质清单和扫描件对应。
不要只把注释当趣味文本。对历史软件而言,注释常常承担需求说明、运行条件和设计理由的作用。结合相邻模块、符号定义和原始清单页码阅读,才能避免把一个局部标签误解为完整功能。
如何编译和模拟运行
Apollo-11 仓库的 README 明确把编译需求指向 Virtual AGC。推荐流程是:
- 保留 Apollo-11 仓库作为历史源码和文件索引;
- 阅读 Virtual AGC 当前平台的构建说明;
- 使用其中的
yaYUL汇编器和 AGC 模拟器; - 对照目标程序版本选择 Comanche 或 Luminary 源码;
- 比较汇编结果、校验和与项目提供的参考信息。
Virtual AGC 支持的平台、依赖和构建命令可能随版本变化,执行前应以其仓库最新文档为准。不要假设在 Apollo-11 根目录运行通用的 make 或 npm install 就能得到飞行程序镜像;根目录中出现现代项目文件,并不改变 .agc 历史源码的实际工具链。
如何验证转录是否准确
这个项目欢迎贡献,但修正必须以原始扫描件为依据。发现可疑字符或拼写时,建议按以下步骤处理:
- 在目录
README.md中找到对应的原始页码; - 打开项目链接的 Comanche 055 或 Luminary 099 扫描资料;
- 对比代码、注释、符号和页码标记;
- 阅读
CONTRIBUTING.md; - 提交只包含明确转录差异的 Pull Request。
不要为了统一大小写、修正历史拼写或采用现代格式而批量格式化源码。历史档案项目首先追求可追溯性,一次看似整洁的机械修改可能让校对工作更困难。
常见问题
这是 Margaret Hamilton 一个人写的吗?
不是。仓库的合同与审批资料列出 Margaret H. Hamilton 为 Colossus Programming Leader,同时也记录了多位项目负责人。Apollo 软件由团队协作完成,把整个仓库归于单个程序员并不准确。
GitHub 上的代码就是飞船当年保存的原始文件吗?
更准确地说,它是根据 MIT Museum 保存的纸质清单扫描件转录并为 yaYUL 适配的版本。仓库保留了原始程序内容和页码对应关系,但载体与格式已经过数字化整理。
为什么分成指令舱和登月舱两套程序?
两个飞行器承担的任务不同。指令舱要处理轨道、姿态、交会和再入等工作,登月舱则要完成下降、着陆、月面起飞和交会,因此各自使用针对任务设计的 AGC 程序。
可以把这些代码直接用于现代航天系统吗?
不应这样做。该仓库适合历史研究、计算机体系结构学习和模拟实验,不是经过现代环境验证的生产软件。现代安全关键系统需要独立的需求、验证、认证和硬件适配流程。
总结
阅读 Apollo 11 源码的正确入口不是从第一行硬啃到最后一行,而是先区分 Comanche055 与 Luminary099,利用目录索引找到任务模块,再结合原始页码、AGC 指令集和 Virtual AGC 工具链逐层深入。这个仓库既是一份可搜索的历史软件档案,也展示了在资源极其有限的计算机上,飞行控制、任务调度、告警恢复和人机交互如何被组织成完整系统。
模拟与编译工具:Virtual AGC