2019年7月20日,是有纪念意义的一天,这天不是因为广大网民帮周杰伦在新浪微博上的超话刷到第一,而是阿波罗登月的50周年的纪念日。早在几年前,在Github上放出了当年Apollo飞船使用的源代码(当然是汇编的),但完全不明白为什么这几天会有一些中国的小朋友到这个github的issue里灌水……,人类历史上这么伟大的一件事,为什么不借这个机会学习一下呢?下面是一些阿波罗登月与程序员相关的小故事,顺着这些东西,你可以把你的周末和精力用得更有价值。
首先,要说的是Apollo 11导航的源代码,这些代码的设计负责人叫Margaret Heafield Hamilton ,是一个女程序员,专业是数学和哲学,1960年得到一个MIT麻省理工大学的临时的软件开发职位,负责在PDP-1和LGP-30上运行天气预报的软件(注:在计算机历史上,PDP系统机器被称为Hack文化的重要推手,PDP-11推了Unix操作系统,而Unix操作系统则是黑客文化的重要产品。参看《Unix传奇》)。然后,她又为美国空军编写探测知敌方飞行的软件,之后,于1965年的时候,她加入了MIT仪器实验室,并成为了这个实验室的主管,这个实验实就是Apollo计划的一部分,她负责编写全新的月球登录的导航软件,以及后来该软件在其他项目中的各个版本。
上图是Hamilton站在她和她的麻省理工团队为阿波罗项目制作的导航软件源代码旁边,在Github上的开源的代码 – Apollo-11 (2016年开源)。我们可以看到,有两个重要的目录,一个目录叫“Comanche055”,一个目录叫“Luminary099”,前者是指挥舱用的(英文为 Command Module )后者为登月舱用的(英文为 Lunar Module),这里需要说明一下的是,指挥舱是把登录舱推到月球上,在返回的时候,登录舱是被抛弃掉的,而返回到地球的是指挥舱。如果你想看这两份源代码的纸版,你可以访问这两个链接:Comanche 55 AGC Program Listing 和 Luminary 99 REv.1 AGC Program Listing。其中的55 和 90 是各自的build 版本号。
我们细看一下,这些文件的日期是,1969年7月14日,而Apollo 11登月的日期是1969年7月16日起程,7月19日经过月球背面,7月20日下午8点登月。代码写好,两天后就直接上生产,然后就登月,还是导航代码,这代码写的的健壮性得有多强。
如果你仔细比较一下这两个目录中的文件,你会发现有些文件是一样的,不但文件名一样,而且内容也一样。这说明这两个模块中的一些东西是相似的。
这些代码应该是很难读了,因为当时写这些代码的时候,C语言都没有被发明,所以基本上来说都是汇编代码了,而且还可以发现,这些代码的源文件全是以agc后缀结尾的, 看来这还不是我们平时所了解的汇编,所谓的AGC代表了运行这些代码的计算机 – Apollo Guideance Computer 。沿着这个Wikipedia的链接,你可以看到AGC这个电脑的指令是什么样的,看懂那几条指令后,这些源代码也就能读懂了。当然,因为是写成汇编的,所以,读起来还是要费点神的。不过,其中有一个文件是 LUNAR_LANDING_GUIDANCE_EQUATIONS.agc 你会不会很好奇想去看看?
打开源文件,你还可以看到每个文件都有很多很多的注释,非常友好,但是也有一些注释比较有趣。这里有一组短视频带你读这些代码 – Exploring the Apollo Guidance Computer(AGC) Code,一供10个小视频,每个2分钟左右,如果你英文听边还行(我觉得很容易听懂),可以看看,了解一下AGC的工作方式,挺有趣意思的。
当时的AGC有32公斤,主频只有2MHz,2K的RAM,36K的ROM。嗯,当年就是这么一个小玩意,把人送上了月球,今天,一个聊天程序就占内存几GB……
下面是AGC在Apollo 1指挥舱里的样子(图片截自上面的视频),这个高质量的3D扫描来自 Simithsonian 3D: Apollo 11 Command Module (我觉得美国人干这些事干就是很漂亮啊,这种高清的3D扫描太牛了,如果你仔细看,这个舱里还有宇航员在舱壁上的手写)
这个AGC的操作界面又叫DSKY – Display 和 Keyboard的缩写,下图是一个 AGC 模拟器,其官方主页在 https://www.ibiblio.org/apollo/源代码在 Github/VirtualAGC。在这个界面上我们可以看到:下面的键盘上左边有两个键,一个是动词Verb一个是名词Noun,Verb指定操作类型,Noun指定要由Verb命令修改的数据。右边的显示器下面有三个5位的数字,这三个数值显示表示航天器姿态的矢量,以及所需速度变化的显示矢量。是的,当年的导航就靠这三个数字和里面的程序了。
如果你想了解AGC更多的细节,你可以看看 这篇 AGC for Dummies。这篇文章讲述了AGC这个嵌入式系统的背景和操作指令。一份详细的AGC 汇编语言手册可以让你了解更多的细节。
另外,我在Youtube上找到了一个讲当时Apollo电脑的纪录片 – Navigation Computer,太有趣了。比如:21分51秒开始讲存储用的 Rope Memory 绕线内存,Hamilton 也出来讲了一下在这种内存上编程,画面切到一个人用个比较长的金属针在一个像主板一样的东西上,左右穿梭,就像刺绣一样,但是绣的不是图案,而是程序……太硬核了,真正的通过“硬编织”的方式来写程序。
看完上面这个纪录篇,我是非常之惊叹,惊叹于50年前的工程能力,惊叹于50年前这些人面对技术的的一丝不苟,对技术的尊重和严谨的这种精神和方法,一点都不比较今天差。
不过,最牛的还不是这个,我在Hamilton的Wikipedia词条上找到了他说的一个事件—— 当年Apollo登陆雷达开关放在了错误的位置,导致AGC收到了不少错误的信号。结果就是AGC既得执行着陆必须的计算,又要接受这些占用其15%时间的额外数据。但是AGC的程序居然可以用高优先级的任务打断低优先级的任务,于是,AGC自动剔除了低级别的任务以保证了重要的任务完成。Hamilton 原话说—— 如果当时的程序不能识别错误并从错误中恢复,我怀疑阿波罗不能成功登月。if the computer hadn’t recognized this problem and taken recovery action, I doubt if Apollo 11 would have been the successful moon landing it was。
看到这里,你有没有觉得——“这个女程序员的一小步,是整个人类的一大步”?
Hamilton 的牛逼之外还在于,她是第一个将“软件工程”提出来的人,在MIT,她想让软件开发就像其它工程一样,有相应的工程纪律,给于相关的尊重,于是她创造了Software Engineering这个词。2018年,IEEE在纪念软件工程50周年的时候,他们把 Hamilton 请过去讲了一个叫 What the Errors Tell Us 的主题。她绝对可以称得上是程序员的Pioneer。
三年前,Apollo的源代码被开源时候,Twitter有个叫 Lin Clark 的人发了一条推:“我妈50年前的代码被放到Github上了”,虽然,她不是 Hamilton 的女儿,但她妈妈也是Apollo其中一个程序员,现在Lin Clark同样也是一个程序员,目前在 Mozilla工作,Staff Engineer,专长 WebAssembly, Rust, 和 JavaScript ,也是个非常厉害的程序,Youtube上各种演讲,也是一个跟他妈妈一样牛的人。
当她在Twitter上这么自豪地发了一条这样的推后,我不知道各位有什么想法?想不想你的后代在未来也会这样自豪的发条微博?
最后,尤其是想对那些到Apollo源代码的issue里发spam垃圾信息的人说一下,你看看人家,再看看你们自己,你们是不是想让你们的孩子在登月100周年纪念的时候说——50年前我爹那个傻叉在Apollo的github的issue列表时写了些垃圾,还以为自己多机灵?!
精彩回顾