Apollo 11 源代码:1969 年登月的那个程序,现在公开在 GitHub 上
1969 年 7 月 14 日,MIT 仪器实验室。Margaret Hamilton 和她的团队在一份打孔纸带上打完了最后一行代码。这份代码将控制 Lunar Module(登月舱)的 Apollo Guidance Computer(AGC),把阿姆斯特朗和奥尔德林送到月球表面。
目录
Apollo 11 源代码:1969 年登月的那个程序,现在公开在 GitHub 上
仓库:chrislgarry/Apollo-11
语言:AGC 汇编(yaYUL)
Stars Today:496
创建时间:2014-04-03
版权:Public Domain
一份 57 年前的代码
1969 年 7 月 14 日,MIT 仪器实验室。Margaret Hamilton 和她的团队在一份打孔纸带上打完了最后一行代码。这份代码将控制 Lunar Module(登月舱)的 Apollo Guidance Computer(AGC),把阿姆斯特朗和奥尔德林送到月球表面。
代码的标题页写着:
Luminary099
Part of the source code for Luminary 1A,
the Lunar Module's (LM) Apollo Guidance Computer (AGC)
for Apollo 11
Assemble revision 001 of AGC program LMY99
by NASA 2021112-061
16:27 JUL. 14, 1969
57 年后,这份代码在 GitHub 上。任何人都能读、能 fork、能提交 PR。
AGC:4KB RAM 的计算机
Apollo Guidance Computer 的规格在今天看来像是另一个维度:
| 参数 | AGC (1969) | 你的手机 (2026) |
|---|---|---|
| RAM | 4KB(磁芯存储) | 12-16GB |
| ROM | 32KB(绳芯存储) | 256GB-1TB |
| 时钟频率 | 1.024 MHz | 3+ GHz |
| 字长 | 16-bit | 64-bit |
| 重量 | 70 磅(32kg) | 200g |
| 功耗 | 55W | 5-10W |
整个 Luminary099(登月舱程序)的源代码不到 32KB。这意味着——整个登月程序的二进制文件,比你手机上的一张 JPEG 照片还小。
绳芯存储:把代码编进绳子
AGC 的 ROM 不是芯片,是绳子。
确切地说,是「绳芯存储」(Core Rope Memory)。原理是:穿过磁环的导线代表「1」,绕过磁环的导线代表「0」。工人(主要是女性,被称为「LOL Memory」,Little Old Lady Memory)手工把导线穿过或绕过几千个磁环,把程序「编」进绳子。
一根绳子存储 6KB。整个 AGC 程序需要好几根绳子。这些绳子重达几公斤,但几乎不会出错——因为物理穿线就是程序本身,一旦编好就是只读的。
这是人类历史上最极端的「硬件即软件」案例。代码不是存在介质上——代码就是介质。
1202 Alarm:代码救了任务
1969 年 7 月 20 日,登月舱 Eagle 正在下降到月球表面。阿姆斯特朗看着仪表盘,突然看到计算机报警灯亮了:
1202
1202 是 AGC 的错误码,意思是「执行溢出」(Executive Overflow)——计算机的任务排队太长,来不及处理。
在今天的电脑上,这相当于 CPU 占用率 100%。但在登月途中,这意味着任务可能要中止。
26 岁的 NASA 工程师 Jack Garman 翻了一下他的笔记——那是他和 Margaret Hamilton 团队整理的「所有可能的 AGC 错误码及应对」清单。1202 的旁边写着:「如果只是间歇出现,可以继续」。
AGC 的设计有一个关键决策:优先级调度。当任务排队溢出时,低优先级任务被丢弃,高优先级任务(如导航和控制)继续执行。1202 报警说明计算机在丢弃一些不那么重要的任务(比如雷达数据处理),但核心控制循环没断。
阿姆斯特朗继续手动驾驶 Eagle 降落。计算机在报警,但一直在工作。最终,Eagle 静静地停在静海基地。
这个「优先级调度」的概念,后来成了所有实时操作系统的核心设计原则。你手机上的操作系统今天还在用类似的优先级队列——只是不会告诉你它在丢任务。
Margaret Hamilton 和「软件工程」
Margaret Hamilton 是 Apollo 11 软件团队的负责人。她的签名出现在 Luminary099 的提交页上:
Submitted by:
Margaret H. Hamilton
Colossus Programming Leader
Apollo Guidance and Navigation
28 Mar 69
她在 Apollo 项目期间创造了一个词:「软件工程」(Software Engineering)。当时很多人觉得这是玩笑——软件怎么能叫「工程」?但 Hamilton 坚持认为,写代码应该像造桥一样有规范、有测试、有容错设计。
她还有一个著名的轶事。在 Apollo 8 任务前,她 4 岁的女儿在模拟器上玩,误触了一个「P01」模式选择键,导致导航数据被清零。Hamilton 提出应该在软件里加保护,防止飞行员误操作。NASA 的回复是:「飞行员不会犯这种错」。
Apollo 8 发射后,飞行员 Jim Lovell 确实误触了 P01。Hamilton 和团队连夜恢复了数据。从此,所有航天软件都加入了「用户输入验证」。
代码本身:AGC 汇编
AGC 的汇编语言叫 yaYUL(Yet Another Universal Language),由 Ron Burkey 维护。
代码风格非常独特。看一段 Luminary099 的实际代码:
# LUMINARY 1A REV 001
# 16:27 JUL. 14, 1969
2V25D300 VN 25D3
# DAP EXIT ROUTINE
2V25D325 TC BANKCALL
2V25D326 CADR DAPEXIT
每一行以地址开头,然后是指令。没有变量名、没有函数调用语法(用 TC = Transfer Control 代替 CALL)、没有结构体。所有逻辑都是地址跳转和寄存器操作。
但在这堆看似原始的汇编里,藏着一些令人惊叹的设计:
- 优先级调度器:管理多个并发任务,按优先级执行
- 虚拟内存:用「bank switching」在 4KB RAM 里映射更大的地址空间
- 容错恢复:遇到错误自动重启,恢复关键状态
- 增量计算:用整数增量更新导航解,避免浮点运算
为什么 57 年后还有人 star
chrislgarry/Apollo-11 仓库创建于 2014 年,至今仍在获得 star。原因不只是「怀旧」。
1. 它是人类第一个「生命攸关」的软件。这个程序的 bug 会直接导致人命损失。Hamilton 的团队用了极端的测试和验证方法——这些方法至今影响航天软件工程。
2. 它是「软件工程」的起源。这个词在这里诞生,然后传播到整个行业。
3. 它是一个 4KB 系统的极限案例。在 4KB RAM 上实现自主登月,需要的不是更多硬件,而是更好的工程。这是对今天「算力不够就加卡」思维的对照。
4. 它是 Public Domain。没有版权限制,任何人可以学习、修改、重新编译。Virtual AGC 项目甚至提供了模拟器,你可以在自己的电脑上运行 Apollo 11 的原始代码。
5. 它提醒我们:代码的寿命可以超过硬件。AGC 的硬件早已退役,但代码还在。57 年后,我们仍然能读懂它、学习它、被它启发。
怎么读这份代码
仓库结构:
Comanche055/— 指令舱(Command Module)程序Luminary099/— 登月舱(Lunar Module)程序CONTRIBUTING.md— 如何提交 PR(是的,57 年前的代码仍在接受 PR)CONTRACT_AND_APPROVALS.agc— 原始合同和审批页
如果你只想读故事,从 Luminary099/ 目录开始,找到注释最多的文件——那些注释是 Margaret Hamilton 团队留下的,比代码本身更有信息量。
一句话总结
4KB RAM,32KB ROM,1MHz 时钟。MIT 的团队用这个配置写出了能自主登月的程序。57 年后,这份代码在 GitHub 上公开。它提醒我们:软件工程的本质不是算力,是约束下的清晰思考。
项目地址:https://github.com/chrislgarry/Apollo-11
模拟器:https://www.ibiblio.org/apollo/