怎么读这一册。 它是这个系列的第四本,也是第一本「对照读」的:把两份飞控软件并排摆开,看同一个计算平台怎么长出两种形状。前三册讲过的内容不再重复。先纠正一个常见错误 :土星五号 S-IVB 上那台计算机叫 LVDC(IBM 研制),与 AGC 是两条不同的产品线。「指令舱一台、登月舱一台、加上 S-IVB 上备用一台 AGC」这个说法不成立,本册不采用。本册不做逐行 diff。 逐字节 diff 只在第 6 章出现,且只比对同一个例程——整文件 diff 对理解「为什么不同」毫无帮助。证据分五类 ,读到任何一句先看它属于哪一类:机器实证 可复跑,源码实证 标了文件行号,外部资料 单独标记,作者推导 给出口径与边界,解释性类比 只是桥、不算证据。
比较矩阵 先建矩阵,再选案例——本册只讲这 8 个
# 案例 登月舱文件 指令舱文件 非空行(LM/CM) 源码相似 机器码相似 案例角色 要回答的工程问题 1 圆锥曲线库 CONIC_SUBROUTINES.agc CONIC_SUBROUTINES.agc 1,793 / 1,781 0.9703 0.6183 同源候选 两条船都要算轨道,哪些数学代码可以复用 2 解释器 INTERPRETER.agc INTERPRETER.agc 2,533 / 2,533 0.9950 0.7545 近似源码 源码很接近,为什么汇编结果不一样 3 变量分配表 ERASABLE_ASSIGNMENTS.agc ERASABLE_ASSIGNMENTS.agc 2,060 / 2,990 0.3039 — 数据布局 变量布局能解释哪些机器码差异 4 光学瞄准 AOTMARK.agc SXTMARK.agc 616 / 613 不同文件 VACSTOR 0.000 接口分化;VACSTOR 为 C 类 用星校惯性平台,两套硬件怎样影响代码 5 推力控制 TRIM_GIMBAL + THROTTLE 7 个 TVC 文件 740 / 2,492 不同文件 — 接口分化 控制推力方向与大小,执行机构不同会怎么写 6 名词表 PINBALL_NOUN_TABLES.agc PINBALL_NOUN_TABLES.agc 866 / 829 0.5972 0.4692 表格分化 显示面板同型,能问的东西一样吗 7 定时中断 T4RUPT_PROGRAM.agc T4RUPT_PROGRAM.agc 1,151 / 1,253 0.6824 0.4156 调度分化 定时中断到来时该干什么,两边一样吗 8 备份机接口 AGS_INITIALIZATION.agc (无对应模块) 213 / — — — 单侧模块(D) 为什么只有登月舱有 AGS 初始化接口
五种内容,五种证据边界 本册把事实和解释分开摆放。读到任何一句,先看清它属于哪一类。
作者报告·未独立复现 原稿报告了汇编、静态计数和映像比较的结果,但本次缺少原工具、版本与输出,不能复跑核实。例如「1,502 个可比符号块、机器码逐字一致率 50.77%」。汇编出机器码、数出相同字,也不等于执行了这些代码,更不等于完成飞行仿真。
源码实证 直接引用源码文本,给出文件路径、标号或注释锚点;原行号保留作定位线索,原统计版本待补,不能保证当前仓库仍在同一行。本次明确核对的 raw 单文件见审校记录。例如 CONIC_SUBROUTINES.agc 中的 ASSEMBLY - COLOSSUS REVISION 88。
外部资料 MIT 博物馆硬拷贝、任务报告、程序备忘录等外部来源。保留来源,与源码证据分开;未在本次逐页核对的图像、史实和秒级时间不宣称已经复核。
作者推导 从所列文本、数字和方法提出解释,说明口径及边界;能手算的算式与必须取得原始材料才能重跑的统计,分开交代。
解释性类比 为了让不熟悉这台机器的人看懂而打的比方。类比只是桥,不是证据;桥过了就该扔掉。
0 两个脑子同一套计算平台,形成两个分别命名和发布的软件产品
1969 年 7 月 16 日,土星五号从肯尼迪航天中心起飞。飞船上装着两台制导计算机:指令舱一台,登月舱一台,同属 Block II AGC 体系——采用共同的体系结构、存储规格和同型人机界面。但「同一套硬件」不等于「两个实物一模一样」:装配批次、接口配置、装进绳芯的程序都可以不同。两套软件各有自己的版本标识,同时保留明显的程序家族关系。 全册考察的主线是:较通用的计算与基础设施可以复用,贴近任务与设备的部分往往分化;这是一条观察线索,不是没有例外的分层定律。
先打个比方
同一个型号的笔记本,一台装着给会计用的软件,一台装着给设计师用的软件。硬件一样,插上电以后完全是两个世界。这一册要问的是:是什么把同一个平台,捏成了两个不同的脑子。
当时的处境
先把一个常见误会说清楚。土星五号火箭还有一台计算机,装在 S-IVB 上方的仪器舱里,叫 LVDC(Launch Vehicle Digital Computer,运载火箭数字计算机),由 IBM 研制。它不是 AGC,是不同的产品线 :指令集、字长和存储组织不同。因此,「加上 S-IVB 上备用一台 AGC」的说法不成立。本册比较的是指令舱与登月舱的两台 AGC,而不是任务中所有计算设备。
源码线索 登月舱程序的扉页。题头印着 `16:27 JULY 14, 1969`,是距发射两天的清单时间标记,不是软件两天前才定版的证据;R00007 给出正式别名:THIS PROGRAM IS REFERRED TO AS LUMINARY 1A 。(图像本次未复核。)源码实证 指令舱程序的扉页,题头为 `10:28 APR. 1, 1969`,比上一张早三个半月。原图注记述星号框写着 COLOSSUS 2A ,SUBMITTED 栏为 MARGARET H. HAMILTON(Colossus Programming Leader),APPROVED 签字日期为 28 MAR 69;这些图像细节本次未复核,不能由题头打印日期替代审批或定版日期。
同一块硬件,两份软件
AGC Block II(两侧完全相同)
36,864 字绳芯只读存储 + 2,048 字磁芯可写存储 · 同一种基本逻辑门搭成
指令时间 11.72 微秒 · 字长 15 位数据 + 1 位奇校验
任务需求在这里开始分流
登月舱 · LUMINARY 1A
Luminary099 92 个源文件
要把两个人放到月面上
· 下降与着陆制导
· 着陆雷达、节流阀
· 配平万向节(不用摆动喷管)
· 对准光学望远镜 AOT
· 给备份计算机 AGS 喂数据
独有 36 个文件
指令舱 · COLOSSUS 2A
Comanche055 85 个源文件
要把三个人带回来
· 再入制导(P61–P67)
· 推力矢量控制(摆动喷管)
· 空间六分仪 SXT
· 星表、再入词表
· 导航精度标定与对准
独有 29 个文件
两侧同名文件 56 个 · 同源例程 1,502 个 · 共同符号 4,192 个
图 1 共同的 AGC Block II 平台与两套软件。按作者报告的文件清单,登月舱独有 36 个文件名,指令舱独有 29 个,两侧同名 56 个。源码实证 Luminary099/ASSEMBLY_AND_OPERATION_INFORMATION.agc(Notations on the hardcopy document 段;原行号不适用)
## Notations on the hardcopy document read, in part:
##
## Assemble revision 001 of AGC program LMY99 by NASA 2021112-061
## 16:27 JULY 14, 1969
硬拷贝注记的现代转录给出:清单装配修订号 001、程序代号 LMY99、文件号 2021112-061、时间 1969 年 7 月 14 日 16:27。它与文件头的 Luminary 1A build 099 属于不同层次的标识,不能混读。日期确实距发射两天,但只说明这份清单记载的时刻,不能据此确定飞行软件的冻结、制造或装船日期。 当前 `.agc` 中带 `##` 的这一段是现代转录文字,不是原件本身。
源码实证 Comanche055/ASSEMBLY_AND_OPERATION_INFORMATION.agc:30-36(硬拷贝题头转录)
## Notations on the hardcopy document read, in part:
##
## Assemble revision 055 of AGC program Comanche by NASA
## 2021113-051. 10:28 APR. 1, 1969
##
## This AGC program shall also be referred to as
## Colossus 2A 指令舱的硬拷贝注记给出:修订号 055、程序名 Comanche、文件号 2021113-051、时间 1969 年 4 月 1 日 10:28,并注明「本程序亦称 Colossus 2A」。两份记录的文件主编号相邻(2021112 / 2021113),清单时间相差三个半月;完整文件号及修订后缀不同。 这不等于两个飞行软件的定版日相差三个半月。
作者报告·未独立复现 文件统计(vol4_matrix.py 未附;原统计版本待补)
Luminary099 : 92 个 .agc 文件
Comanche055: 85 个 .agc 文件
同名文件 : 56 个
LM 独有 : 36 个
CM 独有 : 29 个 口径据作者说明为文件名归一后比较,行数按非空行计。若 92、85、56 这三个输入成立,则 LM 独有 92−56=36,CM 独有 85−56=29。两树共有 177 个文件实例 ,其中独有实例为 36+29=65,占 65/177≈36.7% ;若按去重后的文件名并集 计,分母是 92+85−56=121,独有名称占 65/121≈53.7% 。不能拿 56 个共同名称直接除以 177 个实例,再说「三分之二独有」。这里只校正算术与分母,不宣称已重做文件统计。
● 两台 AGC 属于共同硬件体系,软件各有发布标识。 登月舱为 Luminary 1A(build 099),指令舱为 Comanche 055(亦称 Colossus 2A)。
● 火箭上还有 LVDC,但它不是 AGC。 它位于 S-IVB 上方的仪器舱,不是备用 AGC。
● 两份清单的题头时间相差三个半月 ,不是已经核实的定版日期差。要确定冻结、绳芯制造及装船时间,需要另外的生产与配置记录。
● 本册要回答的不是「它们有什么不同」,而是「同一个计算平台,任务需求怎么把软件捏成了两种形状」。
1 同一个底盘要说清「分叉」,先说清「同源」
两个产品是否存在家族联系,不能只凭相似度猜;源码中保留的历史版本标记是线索。现代 Git 提交主要记录转录与维护,也不能直接冒充 1960 年代的开发历史。前代注释能支持关联,却未必单独还原完整迁移路径。
先打个比方
两栋楼的预制板上印着相同厂名和批次,是来源相关的线索;它不说明整栋楼完全一样,也不能代替完整施工记录。源码里的 ASSEMBLY - COLOSSUS REVISION 88 就像这样的批次标记。
当时的处境
MIT 仪器实验室(Instrumentation Lab)当时维护的不是「两个程序」,而是一个程序家族 :指令舱那条线走过 Sundisk、Colossus、Comanche;登月舱那条线走过 Sundance、Luminary。每条线有自己的版本号。子程序在家族内部流动时,注释里的旧装配标记往往不被清掉——这就给我们留下了一层考古地层。
四层比较:越往下越硬,也越难读
① 文件层
谁有谁没有
→ 回答:任务范围差多少
实测:LM 独有 36 个文件,CM 独有 29 个文件,同名 56 个
② 模块层
是不是同一份源
→ 回答:有没有共同来源
证据取硬拷贝题头与源码注释里的装配标记,不取 git 历史
③ 控制流层
同名例程怎么走
→ 回答:同一件事是不是两套装法 ★ 最重要
实测:A 类 89 例(5.9%)/B 类 1,037 例(69.0%)/C 类 376 例(25.0%)
④ 机器码层
绳芯里实际是什么
→ 回答:源码说的和机器做的一致吗
★ 只有在这一层才动用逐字 diff,且只比同一例程,不比整个文件
证据金字塔(可信度自下而上递增):
源码文字 → 源码结构 → 控制流 → 数学/数据 → 汇编产物 → 绳芯二进制 → 任务历史
逐字节 diff 落在「绳芯二进制」这一层:它很硬,但它只能告诉你「不一样」,
不能告诉你「为什么不一样」。所以本册把它放在第 6 章,不当主角。
图 2 四层比较法。最底层按可对应的符号块逐字比较;第 6 章展示具体编码,不用全文件字节 diff 代替工程问题。源码实证 Luminary099/CONIC_SUBROUTINES.agc:41 / Comanche055/CONIC_SUBROUTINES.agc:46
# MOD BY KRAUSE ASSEMBLY - COLOSSUS REVISION 88
# MOD BY KRAUSE ASSEMBLY - COLOSSUS REVISION 88 原稿报告这条注释在两侧各出现 5 次;本次确认两侧存在该标记,未重跑全量计数。同一个修改人和版本标记出现在两个产品中,支持两者具有代码谱系联系。 仅凭注释不能断定完整轨道库由某一侧单向迁入另一侧,更不能断定迁入后未经修改。
源码实证 两侧 CONIC_SUBROUTINES.agc:LM 第 70 行 / CM 第 75 行
# MOD BY KRAUSE ASSEMBLY - COLOSSUS 103 AND SUNDANCE 222 这一条同时提到 COLOSSUS 103(指令舱线)和 SUNDANCE 222(登月舱线)。它支持该修改记录涉及两条程序线;原稿报告各出现 1 次。同列两个版本号不等于已经还原两边修改的时间顺序、范围或传递方向。
源码线索/计数为作者报告 五组共同前代标记(原脚本未附;单 # 注释亦须结合扫描件判断来历)
ASSEMBLY - COLOSSUS REVISION 88
LM 5 次 / CM 5 次 CONIC_SUBROUTINES.agc LM:41 CM:46
ASSEMBLY - COLOSSUS 103 AND SUNDANCE 222
LM 1 次 / CM 1 次 CONIC_SUBROUTINES.agc LM:70 CM:75
ASSEMBLY SUNDISK REV. 82
LM 1 次 / CM 1 次 IMU_MODE_SWITCHING_ROUTINES.agc LM:765 CM:763
ASSEMBLY SUNBURST REV 5
LM 1 次 / CM 1 次 WAITLIST.agc LM:43 CM:43
ASSEMBLY SUBROUTINE UTILITYM REV 25
LM 1 次 / CM 1 次 AGC_BLOCK_TWO_SELF-CHECK.agc LM:34 CM:37 据原统计,五组标记在两侧同名文件中出现次数一致。 它们使轨道数学、惯性平台模式切换、定时任务调度、机器自检成为有依据的家族共用候选。标记不等于完整模块内容一致;其中平台模式切换和自检还依赖具体机器与接口,不能一概称为「与硬件无关」。
作者报告·未独立复现 脚本 vol4_addrs.py(符号表统计报告)
共同符号 4,192 个(登月舱 7,104 个 / 指令舱 7,217 个)
可擦除存储(RAM 变量):共同 476 个,同址 87 个 (18.3%),异址 389 个 (81.7%)
固定存储地址类符号:共同 3,054 个,同值 317 个 (10.4%),异值 2,737 个 (89.6%) 原稿报告 MPAC 在两侧均为 E00154。 MPAC 是解释器进行多精度运算的重要工作区;同址名单还列出 ADIAX / ADIAY / ADIAZ、AZO / AXO、CDUIND、COMMAND 等,共 87 个。这提示共同基础设施的一些布局具有稳定性,但仅凭所列例子不能证明全部 87 个都属于共同层。4,192 个共同符号中,上表只列出 476+3,054=3,530 个,其余 662 个的类别与筛选规则待补;不能把所有符号值都当成存储地址。
作者报告·未独立复现 vol4_select.py(符号块级逐字比对)
A 类(源码 1.000 且机器码 1.000):89 个符号块,546 字
其中「两侧起址不同却逐字相同」的:55 个符号块
DMPNSUB 11 字 LM 03,7316 CM 03,7265
RELTAB 11 字 LM 02,4066 CM 02,4072
MATMOVE 10 字 LM 14,3377 CM 14,3053
VROUND 10 字 LM 03,7140 CM 03,7107
TPSL1 9 字 LM 02,4404 CM 02,4420
(地址与机器字按原清单用八进制;差值和数量除标 0o 者外用十进制) 原报告中这 55 个符号块在两组不同起址 上产生了相同机器字,MATMOVE 的起址差为 0o324 字。这最多说明这些块在所比较的两种布局 下编码相同,不能推出「装到任何地址都不变」或「不含绝对引用」。如果被引用对象仍在相同地址,即使存在绝对引用,编码也可能不变。固定-固定区的地址窗口无需 bank 切换,但两版同名对象未必被安排在同一地址。要判断位置无关性,需要逐字辨识操作数、引用目标及装配上下文;本册没有完成这一工作。
● 前代注释支持家族关联。 COLOSSUS REVISION 88 留在登月舱轨道库中,但单向迁移路线与整个模块的改动范围仍需历史版本和文献佐证。
● 四个文件是家族共用候选 :轨道数学、惯性平台模式切换、定时任务调度、机器自检。它们在不同层面依赖共同平台,不能统称为完全硬件无关。
● 87 个共同可擦除存储符号同址是作者报告 ,MPAC 是其中一例;分类全集与原符号表仍待提供。
● 55 个符号块在这两种布局下起址不同而编码相同 ,不是位置无关代码的证明,也不是可任意逐字搬运的许可。
2 分叉发生在哪里源码很接近,机器码却有明显差异——变量布局是值得检查的一层
原比较矩阵报告:解释器两边各有 2,533 个非空行,源码相似度 0.9950,机器码逐字一致率 75.45%(均为作者报告,未独立复现)。这提示我们不能只看源码文本,还要看它在哪里、按什么符号定义被汇编。*
*先把话说准:本章提出变量布局可能影响机器字的机制,并给出待复现的统计线索,不声称已经量出它贡献了多少差异。 两条船还有单侧文件、不同模块、不同接口与显示数据等分化;同名代码内部也可能改动。这里重点问:两边共有的源码片段,为什么仍可能产生不同编码。
先打个比方
两家分店照着相近的菜谱做菜,盐罐位置却不同,取盐动作因此不同。这能帮助理解符号与地址的关系;但如果配料定义、计量方式或厨具也不同,仅看菜谱里的同一句话还不能保证做出相同的菜。
当时的处境
AGC 的可擦除存储只有 2,048 字,是紧张资源。大量变量布局集中写在 ERASABLE_ASSIGNMENTS.agc,像一张「户籍簿」。不过其中既有实际分配,也有 EQUALS 别名、固定位置和覆盖区:不一定每多一行就多占一个字,也不是后面的地址必然顺次后移。
同一个变量,在两条船的可写存储里隔了多远
E4 是一块可切换的可写存储区(bank);横轴是区内的地址,单位:字
E4,1400
E4,1777
BETAV
1437
1557
相差 80 字
PHIV
1445
1565
相差 80 字
TFF
1540
1743
相差 131 字
H
1477
1611
相差 74 字
登月舱 Luminary
指令舱 Comanche
共同变量 476 个:同址 87(18.3%),异址 389(81.7%)
图 3 同名变量在两条船可写存储里的住址对比(节选)。共同变量 476 个,同址 87 个(18.3%),异址 389 个(81.7%)。作者报告·未独立复现 vol4_matrix.py(文件级源码相似度;完整归一化规则待脚本确认)
ERASABLE_ASSIGNMENTS.agc 登月舱 2,060 非空行 指令舱 2,990 非空行 源码相似 0.3039
(对照:同名文件里相似度最高的几个)
ASSEMBLY_AND_OPERATION_INFORMATION 1.0000
CONTRACT_AND_APPROVALS 1.0000
AGC_BLOCK_TWO_SELF-CHECK 0.9958
INTERPRETER 0.9950
LATITUDE_LONGITUDE_SUBROUTINES 0.9877
MEASUREMENT_INCORPORATION 0.9862 这份报告中,变量分配表相似度为 0.3039,指令舱版本多 930 个非空行(作者报告,未独立复现),差别值得关注。但非空行包含注释、别名与分组,不能直接等同于新增变量数量;纯注释文件在去注释后可能成为空序列,其 1.0000 得分也不代表相同的可执行内容。
作者报告·未独立复现 脚本 vol4_addrs.py(共同变量的地址偏移)
同名变量在两条船上的住址(同一个 E-bank 内的偏移)
BETAV LM E4,1437 CM E4,1557 差 +80 字
PHIV LM E4,1445 CM E4,1565 差 +80 字
H LM E4,1477 CM E4,1611 差 +74 字
TFF LM E4,1540 CM E4,1743 差 +131 字
CENTANG LM E7,1620 CM E7,1753 差 +91 字
TITER LM E7,1613 CM E7,1664 差 +41 字
CSTH LM E5,1731 CM E5,1733 差 +2 字
WHOCARES LM E7,1471 CM E7,1777 差 +198 字(报告中的最大值;为哑符号)
NN LM E7,1466 CM E7,1765 差 +191 字
同 bank 内异址 319 例:偏移绝对值中位数 23 字,最大 198 字,最小 1 字
指令舱地址更大的 230 例,更小的 89 例;跨 bank 的 70 例 所列同名符号在同一 E-bank 中出现了不同偏移 ,这是布局不同的线索,不是「多出 930 行导致后面全部顺移」的证明。报告中既有正偏移也有负偏移,还列出 70 个跨 bank 的符号,不能概括成单一整体平移。WHOCARES 的定义为 `EQUALS E7OVERLA`,注释 DUMMY FOR EBANK INSENSITIVE 2CADRS 表明它是服务于地址编码的哑符号;它不是为凑数而新增分配的一块变量存储。原行号 2185 只作线索。
源码实证 两侧 ERASABLE_ASSIGNMENTS.agc(MPAC 那一行)
MPAC ERASE +6 # MULTI-PURPOSE ACCUMULATOR. `MPAC ERASE +6` 在两侧为多功能累加器保留 7 个字;原报告还给出同址 E00154。它能支持一个具体的稳定布局例子,不能单凭这一行推出「共用件都排在前部、任务专属变量都排在后部」,也不能反推出当年先保共用件的设计决策。
作者推导 机制假说(数字为作者报告,箭头不是已验证的因果关系)
任务不同 → 所需状态量、接口和存储安排可能不同
→ ERASABLE_ASSIGNMENTS 的文本与定义可能不同(报告相似度 0.3039)
→ 某些同名符号取值或地址不同(报告同 bank 偏移中位数 23 字)
→ 引用它们的机器字可能不同(还须考虑 bank、指令形式与装配上下文) 这条链给出可检验的机制,不是已经完成的归因。 除恢复原统计输入外,还须把具体差异字连接到具体源码操作数,检查其符号定义与编码规则,才能说某个差异由地址变化造成。原材料既不能给出总体地址成因占比,也不能证明当年的设计动机;解释器 75.45% 与总体 50.77%(均为作者报告,未独立复现)更不能混作同一个样本。
● 变量布局可以影响机器码,但贡献比例未定。 0.3039 的文本相似度和若干异址符号提供检查方向,不能独自完成因果证明。
● 多出的 930 个非空行不是 930 个变量。 注释、EQUALS、覆盖区与 bank 分配都可能影响统计,不能据此推定后续地址整体后移。
● 同址与异址可以并存。 87/389 的分组及所列示例是作者报告;需要完整类别清单,才能判断它们是否集中于某一功能层。
● 机制与动机分开。 逐操作数解释尚待完成,历史上的取舍也不能用当前统计反推。
3 一个要把人放下去按原统计,登月舱有 36 个在指令舱树中无同名对应的文件
它的特有任务包括从月球轨道下降到月面、再上升,以及相应的中止与备份接口。不过「文件名只在一侧出现」不等于功能只在一侧存在:两侧也可能采用不同文件名组织相近的能力。
当时的处境
登月舱下降段要协调可节流发动机、着陆雷达、机组干预、触地关机与中止流程。这组月面着陆需求是登月舱特有的,但手动控制、发动机关机和中止这些抽象能力并非指令舱一概没有。 比较时要分清任务特有的实现与两侧共有的概念。
源码实证 Luminary099/LUNAR_LANDING_GUIDANCE_EQUATIONS.agc(1,286 非空行,登月舱独有)
## Filename: LUNAR_LANDING_GUIDANCE_EQUATIONS.agc
## Purpose: Part of the source code for Luminary 1A build 099.
## It is part of the source code for the Lunar Module's (LM)
## Apollo Guidance Computer (AGC), for Apollo 11. 原报告计 1,286 个非空行,指令舱树中没有同名文件。月面着陆制导是明确的登月舱任务,可作为单侧模块(D)的例子;但「无同名文件」本身不证明其中每一行都没有在别处复用。
源码实证 Luminary099/AGS_INITIALIZATION.agc:34 / :46 / :71
# PROGRAM NAME: AGS INITIALIZATION (R47)
# FUNCT. DESC.: (1) TO PROVIDE THE AGS ABORT ELECTRONICS ASSEMBLY (AEA) WITH THE LEM AND CSM STATE VECTORS
# AGSBUFF (140) CONTAINS AGS INITIALIZATION DATA (SEE :OUTPUT: BELOW) AGS 是登月舱的中止制导系统 ,AEA 是其中承担计算功能的电子组件。源码说明,R47 经登月舱计算机数字下行接口向 AEA 提供 LM 与 CSM 的位置、速度和时刻。它是按操作启动的初始化/更新过程,不是主机状态的无间断镜像,更不能据此承诺主机故障时无缝接管。 指令舱没有这一 AGS 初始化模块,不等于没有任何备用控制方式。AGS/AEA、主 AGC 与火箭仪器舱中的 LVDC 要分开。
【补充】`AGS_INITIALIZATION.agc` 的调用说明为 PROGRAM IS ENTERED WHEN ASTRONAUT KEYS V47E ON DSKY 。代码发送 AGS downlist、等待 20 秒后恢复原下行清单,并包含角度零点与时钟参考的相关处理;这比「一直喂数据」准确。此语境由本次 raw 单文件核对,非原统计复现。
源码实证 Luminary099/THE_LUNAR_LANDING.agc:128-140(另见 :265)
# DDUMCALC IS PROGRAMMED AS FOLLOWS:-
# 2 -
# (RIGNZ - RGU )/16 + 16(RGU )KIGNY/B8 + (RGU - RIGNX)KIGNX/B4 + (ABVAL(VGU) - VIGN)KIGNV/B4
# 2 1 0
# DDUM = -------------------------------------------------------------------------------------------
# 10
# 2 (VGU - 16 VGU KIGNX/B4)
## Page 787
# 2 0
# THE NUMERATOR IS SCALED IN METERS AT 2(28). THE DENOMINATOR IS A VELOCITY IN UNITS OF 2(10) M/CS.
# THE QUOTIENT IS THUS A TIME IN UNITS OF 2(18) CENTISECONDS. THE FINAL SHIFT RESCALES TO UNITS OF 2(28) CS.
# THERE IS NO DAMPING FACTOR. THE CONSTANTS KIGNX/B4, KIGNY/B8 AND KIGNV/B4 ARE ALL NEGATIVE IN SIGN.
这段注释有三点值得读:① 它明确分子、分母及商的定点缩放尺度,最后还需再次移位;AGC 没有硬件浮点指令,这里不能按普通浮点表达式照抄数值。② 标题另引的原第 265 行涉及 P63LM,但它不在上面的节选里;登月舱 P63 与下降制动段的关系需结合该处程序上下文。③ NO DAMPING FACTOR 针对这里的 DDUM 计算,不宜扩张为整个下降控制系统都没有阻尼。
作者报告·未独立复现 脚本 vol4_matrix.py(登月舱独有文件,按非空行排序)
SERVICER.agc 1,436
P32-P35,_P72-P75.agc 1,333
LUNAR_LANDING_GUIDANCE_EQUATIONS.agc 1,286
FLAGWORD_ASSIGNMENTS.agc 993
ATTITUDE_MANEUVER_ROUTINE.agc 978
P-AXIS_RCS_AUTOPILOT.agc 969
AOSTASK_AND_AOSJOB.agc 938
BURN,_BABY,_BURN_--_MASTER_IGNITION_ROUTINE.agc 872
Q,R-AXES_RCS_AUTOPILOT.agc 774
FINDCDUW_-_GUIDAP_INTERFACE.agc 643
AOTMARK.agc 616
ASCENT_GUIDANCE.agc 610
TRIM_GIMBAL_CONTROL_SYSTEM.agc 537
LANDING_ANALOG_DISPLAYS.agc 518
TJET_LAW.agc 457
... 合计 36 个文件 源码实证 登月舱打印清单第 732 页。原图注指出左侧 `REF n LAST ppp` 为交叉引用,右下 `P41TABLE / P42TABLE / P63TABLE` 含动词—名词信息,`VN` 给出其编号;该页属于前述主点火模块。图像内容本次未重新核对。几个值得单独点出来的: · BURN_BABY_BURN (主点火例程)——名字不用翻译。 · LANDING_ANALOG_DISPLAYS (着陆模拟显示):驱动给宇航员看的着陆点指示与模拟仪表。 · ASCENT_GUIDANCE (上升制导):从月面起飞回轨道用的,指令舱当然不需要。 · P70-P71 :登月舱的中止程序。
● 原报告的 36 个单侧文件名覆盖登月舱多类工作 :下降、着陆、上升、中止和 AGS 接口,也包含服务、姿态及交会相关内容。不能由文件名独有推断「几乎全部功能为 LM 独有」。
● R47 给 AGS/AEA 初始化或更新状态数据 ,不是持续镜像;切换与中止能力还依赖系统状态和机组操作。
● 同一个程序号在两个程序里可以指不同的事 (比如 P63),下一章会看到指令舱那边 P63 指的是再入起始段。程序编号是各机型内部定义的,不是跨机型的全局命名空间。
● AGS、AEA 与 LVDC 不要混称 :AGS 是中止制导系统,AEA 是其中的计算组件;LVDC 是火箭仪器舱计算机,都不是另一台 AGC。
4 一个要把人带回来按原统计,指令舱独有 29 个文件
指令/服务舱组合要把三个人从月球轨道带回地球,最终由指令舱穿过大气层。登月舱不承担地球再入:下降级留在月面,上升级完成交会对接后被抛弃。再入是指令舱独有软件里最鲜明的一条主线,但不是全部 ——同一份清单里还有 SPS 推力矢量控制、惯性平台标定,以及它自己的导航与显示。
当时的处境
再入对航迹角、过载和热载荷有严格约束。角度过浅或过陡都会带来问题,因此软件需要阶段转换、专用控制律和相应的数据;本册不据此给各任务阶段排「容错空间最小」的名次。
源码实证 Comanche055/P61-P67.agc(1,076 非空行,指令舱独有)
# PROGRAM: P61
# EXIT- TO P62
# .... THEN FALL INTO P62
# PROGRAM- P62
# CALLING SEQUENCE- BY V37 OR DIRECTLY FROM P61
# EXIT- TO P63
# PROGRAM- P63
# PROGRAM- P64 P61 至 P67 构成指令舱的再入程序组,但不应把它们画成每次都无条件逐一经过的直线。登月舱没有这套再入实现,却可能使用相同程序号表示别的任务 ,例如 P63,不能说这些编号在那里「一个都没有」。
源码实证 Comanche055/P61-P67.agc(各阶段的进入条件,直接写在代码行尾)
192:P62 TC S61.1 # CHECK STATE VECTOR AND IMU ORIENTATION.
309:P63 TC NEWMODEX
375:P64 TC NEWMODEX # ENTER VIA RTB WHEN .05G IS EXCEEDED.
397:P65 TC NEWMODEX # ENTER VIA RTB WHEN RANGE < 25 N M OF
444:P66 TC NEWMODEX # ENTER VIA RTB WHEN D < Q7 FPSS
470:P67 TC NEWMODEX # ENTER VIA RTB 源码实证 这一页属于后文清单中的 `P37,P70` 文件,而不是 P61–P67。原图注列出 R01 输入、R02 输出及 `R0165 GAMMAEI`(再入飞行路径角)。`P37 IS NOT RESTARTABLE.` 指该程序不具备相应的软件重启恢复支持,不是日常意义上「永远无法再次运行」。图像本次未复核。节选列出了若干进入条件:P64 注释写到超过 0.05g,P65 的距离条件还需连读下一行,P66 引用 D 与 Q7 FPSS。它们表明阶段转换会使用飞行状态判据,但不能由几条行尾注释断言所有阶段都「不靠计时」,也不能把所有判据一律称为直接测得的量。
源码实证 Comanche055/TVCDAPS.agc(TVC 七件套之一,661 非空行)
# FOR THE PITCH AND YAW SPS GIMBAL ACTUATORS DURING TVC (SPS) BURNS,
# EACH ATTITUDE-RATE LOOP INCLUDES GIMBAL ANGLE RATE DERIVATION,
# GIMBAL/BODY AXIS TRANSFORMATION, BODY-AXIS ATTITUDE ERROR TVC 是推力矢量控制 。指令/服务舱的 SPS 通过俯仰、偏航万向支承及作动器调整发动机推力轴方向。登月舱下降发动机也能偏转,并非固定不动;它还具有节流能力。 TRIM_GIMBAL_CONTROL_SYSTEM(Gimbal Trim System,发动机万向修整系统)的 GTS 和 TIMEGMBL 涉及配平与驱动时间,节流另有对应例程。比较应落在执行机构、反馈接口、控制律和调度方式上,而不是「一边转喷管、一边转发动机」的假二分。两边都调推力方向,与设备直接耦合的实现未必能原样共用;只凭这些片段也不足以严格证明一边全为离散控制、另一边全为连续闭环。
作者报告·未独立复现 脚本 vol4_matrix.py(指令舱独有文件,按非空行排序)
P37,P70.agc 1,887
REENTRY_CONTROL.agc 1,365
P32-P33,_P72-P73.agc 1,341
IMU_CALIBRATION_AND_ALIGNMENT.agc 1,284
CM_ENTRY_DIGITAL_AUTOPILOT.agc 1,085
P61-P67.agc 1,076
RCS-CSM_DIGITAL_AUTOPILOT.agc 886
P11.agc 858
JET_SELECTION_LOGIC.agc 825
SERVICER207.agc 693
TVCDAPS.agc 661
SXTMARK.agc 613
ANGLFIND.agc 601
... 合计 29 个文件 源码实证 指令舱打印清单第 844 页,原图注定位为 `REENTRY CONTROL` 的第一页。`EBENTRY = EBANK7`、`EBAOG EQUALS EBANK6` 涉及 bank 定义,`NTRYPRIO EQUALS PRIO20` 涉及优先级,`CM/FLAGS EQUALS STATE +6` 给出状态字别名,不应把四项都解释成借用执行程序状态字。`COME HERE FROM CM/POSE. RESTARTED IN CM/POSE.` 提供进入与重启上下文的线索;上面清单中的 `REENTRY_CONTROL` 即所指文件。图像本次未复核。按原报告,REENTRY_CONTROL(1,365 非空行)+ CM_ENTRY_DIGITAL_AUTOPILOT(1,085)+ P61-P67(1,076)=3,526 非空行 ,这些文件体现再入任务的代码组织。另有 IMU_CALIBRATION_AND_ALIGNMENT(1,284 非空行)。这不表示登月舱无平台对准能力,也不表示行数可直接衡量功能复杂度或运行负载。
源码实证 Comanche055/ASSEMBLY_AND_OPERATION_INFORMATION.agc(原 :1038-1045;OPTION CODES FOR 504)
# 00004 SPECIFY RADAR 1=RR 2=LR R04 SUNDANCE + LUMINARY
# 00005 SPECIFY SOR PHASE 1=FIRST 2=SECOND P38 COLOSSUS + LUMINARY
# 00006 SPECIFY RR COARSE ALIGN OPTION 1=LOCKON 2=CONTINUOUS DESIG. V41N72 SUNDANCE + LUMINARY
# 00007 SPECIFY PROPULSION SYSTEM 1=SPS 2=RCS P37 COLOSSUS
# 00010 SPECIFY ALIGNMENT MODE 0=ANY TIME 1=REFSMMAT +G P57 LUMINARY
# 2=TWO BODIES 3=ONE BODY + G
# 00011 SPECIFY SEPARATION MONITOR PHASE 1=DELTAV 2=STATE VECTOR UPDATE P46 LUMINARY
# 00012 SPECIFY CSM ORBIT OPTION 1=NO ORBIT CHANGE 2=CHANGE P22 LUMINARY 表的实际标题是 OPTION CODES FOR 504,即选项代码表,不是扩展动词表,也不是此处可直接改称的 mode codes 表。 表前说明:通过 V04N06 在 R1 闪示选项代码,请机组在 R2 输入所选值;列名包括 PURPOSE、INPUT FOR COMPONENT 2、PROGRAM(S)、APPLICABILITY。因此 00004、00007 是选项代码,不能当成动词号。表中跨程序线的适用性标注支持家族共同文档约定的存在,不等于两侧实现或实际可选项完全相同,也不能据此确定维护组织与流程。
作者推导 把两张文件清单合成一张能力表(依据:两侧文件清单与各自非空行数)
能力 登月舱 指令舱 共享基础 源码依据
轨道与圆锥曲线计算 有 有 同源线索 CONIC_SUBROUTINES(两侧同名)
月面下降 有 — — LUNAR_LANDING_GUIDANCE_EQUATIONS
月面上升 有 — — ASCENT_GUIDANCE(610 行)
地球再入 — 有 — REENTRY_CONTROL / P61-P67
SPS 推力矢量控制 — 有 — TVC 七件套(2,492 行)
AGS/AEA 初始化接口 有 — — AGS_INITIALIZATION
光学对准惯性平台 有(AOT) 有(SXT) 同一概念层 AOTMARK / SXTMARK(两套代码)
DSKY 人机界面 有 有 同一型硬件 PINBALL 各自维护一份名词表
注:这张表按「能力」组织,不按文件数量——文件数量不是功能复杂度,
一个 1,887 行的文件和二十个 100 行的文件不能直接比。 补这张表,是为了避免把文件数当能力数 。在本表范围内,月面下降、上升、AGS 接口属于登月舱任务,再入与 SPS 专用控制属于指令/服务舱任务;共享或对应能力还包括轨道数学、DSKY、光学对准以及表外的调度和平台基础设施。不能说「重叠的只有 DSKY 和轨道数学」,也不能把数学库整体写成未经修改的同一份源码。
● 指令舱独有的 29 个文件,最鲜明的主线是再入 :REENTRY_CONTROL、CM_ENTRY_DIGITAL_AUTOPILOT、P61–P67 三块加起来 3,526 行;同一份清单里还有 P37,P70(1,887 行)与惯性平台标定(1,284 行)。
● SPS 专用 TVC 是指令/服务舱的重要实现,但推力矢量控制这一能力并非它独有。 原报告选取的 7 个 TVC 文件为 2,492 非空行,LM 的配平与节流两个文件为 740 行,比例约 3.4;这是所选文本范围的规模比,不是复杂度、难度或工作量之比。
● 跨程序线的选项代码表保留共同文档约定。 本节引用的是 OPTION CODES FOR 504,不是动词号表;每行还有适用性范围。
● 同一个 P63 编号可以有不同含义 :LM 指下降制动段,CM 指再入程序中的相应阶段。这说明程序号必须连同软件产品解释,不能只靠数字跨产品寻找等价功能。
5 同名代码到底有多像三个观察层级给出三个相似度数字
原稿报告 88.06%、50.77%、41.39%(均为作者报告,未独立复现),分别涉及归一化源码行序列、机器字和符号名称集合。前两者依赖原脚本、清单及样本筛选,第三者可以由给出的集合大小核算,但输入集合本身仍未复核。
它们不是三个通用的「代码共享率」;不能因为数字精确就说测量已验证,也不能在不同分母之间直接比较谁更真实。
先打个比方
问两个人「你们的文档有多像」,可以有三种问法:句子一字不改的比例、打印出来连排版都一样的比例、用到的专业名词重合的比例。三种问法三个答案,但你不能说其中哪个是「真正的」相似度 ——只能说你问的是哪一种。
当时的处境
要追问共同来源,不能只看相似度高低。第 1 章的历史版本注释为家族联系提供线索;但注释、相似度和共享名称并不自动构成三份相互独立的谱系证据,也不能排除共同更早来源等情况。
同名例程的四种关系(共 1,502 个,按例程数)
类别与判据
例程数 / 占比
A
完全相同
源码与机器码都一字不差
89 例 5.9%
B
结构相似、常数与地址不同
源码相似度 ≥ 0.95,机器码 < 1.000
1,037 例 69.0%
C
同名不同实现
源码相似度 < 0.95:同一件事两套装法
376 例 25.0%
D
同概念角色、无代码对应
只在单侧出现,靠功能对位
36/29 个文件*
B 类是主体:源码几乎不动,机器码大面积不同。
这三个数字说的是同一件事的三种看法,差这么多本身就是线索:
源码层 88.06%(看起来几乎一样) 机器码层 50.77%(实际只有一半) 语义层 41.39%
* D 类按文件计(登月舱 36/指令舱 29),不按例程数。
图 4 符号块的比较分类与单侧模块。原 B 类阈值为源码相似度 ≥0.95 且机器码 <1,占比报告为 69.0%(作者报告,未独立复现);它不等同于所有块源码完全相同。该分类规则未覆盖 0.95≤srcsim<1 且机器码=1 的类别,其数量未经核查。作者报告·未独立复现 vol4_cases.py(前两项按机器字加权;Jaccard 单独按符号集合计算)
【三层相似度指标】(前两项报告样本为 1,502 个符号块 / 17,681 字)
归一化源码行序列相似度 88.06%
机器码逐字一致率 50.77%
符号集合 Jaccard 相似度 41.39%
固定-固定区 源码 94.03% 机器码 65.26% (183 个符号块)
可切换区 源码 87.37% 机器码 49.08% (1,319 个符号块) 三个指标不等于「共享了多少代码」。 源码层按归一化后的行序列计算 `2×匹配行数/(LM行数+CM行数)`,再按块的机器字数加权;不是逐记号相似度。机器码层对齐可比块,统计相同机器字,分母据报告为 17,681 字,但等长筛选和对齐规则待脚本确认。符号 Jaccard 为 `4,192/(7,104+7,217−4,192)≈41.39%`,只度量名称交集占并集的比例。它们不能互相换算或平均。 固定-固定区报告的 65.26% 高于可切换区的 49.08%(均为作者报告,未独立复现),但该区只是无需 bank 切换的寻址窗口,不保证两版同名块起址相同;区域构成、引用目标和源码变化等也可能影响一致率,不能从相关性推出地址稳定性「决定」机器码稳定性。
方法论 原稿测量协议说明(vol4_cases.py 未附;不是已验证的可复现协议)
输入 作者所用两侧 yaYUL .lst 清单(原版本、工具参数与清单待补)
↓ 取源码列 从所选机器字记录提取源码文本;一行产多字等情形须查原脚本
↓ 去注释 在「制表符 + #」处截断(yaYUL 把注释放在这一列之后)
↓ 归一空白 连续空白折成一个空格,去首尾
↓ 比对单元 归一化后的源码行(含标号、操作码、操作数,不含地址列)
↓ 序列比对 difflib.SequenceMatcher 在行序列上找匹配块,
Dice = 2 × 匹配行数 ÷ 两侧行数之和
↓ 加权 每个块得分 × 它的机器字数 n,除以全部可比块的字数之和
↓ 排除 原方法排除 n < 4 的块;这是样本筛选约定,不是「短块没有意义」
已知偏差(以及它们往哪个方向拉数字)
· 按机器字数加权 → 长块影响更大;代码和数据均可能入样
· 行级比对,不对齐记号 → 一行里改一个字符,整行算不同(偏保守)
· 标号参与比对 → 入口同名不代表内部标号同名,不能认为此偏差可忽略
· 常数按字面比对 → 常数真的改了会拉低(这正是第 6 章那个反例的来源)
· 地址列不参与 → srcsim=1 也可能编码不同;全局装配信息未必被取入 这些步骤说明测量思路,但仍不足以保证他人得到同一个数。 还缺源树提交号、yaYUL 版本、完整清单、切块和等长筛选规则、注释解析细节及 SequenceMatcher 参数(包括 autojunk)。一个机器字记录如何关联源行也须核对。srcsim=1 只表示被提取并归一化的行序列相同 ;它不保证整份文件、所有符号定义或装配上下文相同。SETLOC、BANK、EBANK、伪指令/宏式展开和块外定义都可能影响编码;要谈行为等价,还必须检查运行状态与接口。
作者报告·未独立复现 vol4_select.py(原 A/B/C 阈值;仅取长度 ≥4 字的可比符号块)
A 源码相似度 =1 且机器码一致率 =1 89 块 5.9% 546 字
B 源码相似度 ≥0.95 且机器码一致率 <1 1,037 块 69.0% 11,737 字
C 源码相似度 <0.95 376 块 25.0% 5,398 字 原报告把 B 类列为最多的一组,但阈值不等于成因。 B 只表示源码行相近而机器字存在差异,不足以命名为「只改地址」;C 也不自动表示不同算法。三个数量相加为 1,502、字数相加为 17,681,不过原规则漏掉了 `0.95≤srcsim<1 且机器码=1` 的情况。该情况应另列「源码行有差异、机器字相同」类,不能未经脚本核查就断言其数量为零。D 在本册仅表示无可配对块的单侧模块/范围,不纳入这 1,502 个可比块;VACSTOR 有同名配对,按报告应归 C。
作者报告·未独立复现 vol4_cases.py(C 类长块示例;含数据表,并非全是子程序)
IDADDTAB n=180 源码 0.461 机器码 0.156 pinball_noun_tables
NNTYPTAB n=100 源码 0.630 机器码 0.630 pinball_noun_tables
NNADTAB n=100 源码 0.660 机器码 0.580 pinball_noun_tables
STARTSB2 n= 62 源码 0.532 机器码 0.032 fresh_start_and_restart
RUTMXTAB n= 60 源码 0.533 机器码 0.517 pinball_noun_tables
VACSTOR n= 27 源码 0.074 机器码 0.000 aotmark / sxtmark
NOMDNLST n= 26 源码 0.077 机器码 0.038 downlink_lists
PREMM1 n= 30 源码 0.200 机器码 0.000 fresh_start_and_restart 几个值得单独看的块 :VACSTOR 分别在 AOTMARK 和 SXTMARK,报告源码相似度 0.074、机器码 0.000,第 7 章再讨论;它有同名对应,属于 C,而不是 D。NOMDNLST 的 0.077 表示选取的下行清单块文本差异大,不能推出两船全部下行数据完全不同。IDADDTAB 是名词相关地址表,180 字的一致率报告为 15.6%(作者报告,未独立复现);这种数据表不能按子程序或算法来计数。
源码实证 Luminary099/CONIC_SUBROUTINES.agc:41(家族谱系线索,不单独证明迁移方向)
# MOD BY KRAUSE ASSEMBLY - COLOSSUS REVISION 88 这些材料支持程序家族关联,不支持把完整开发过程写成已证实的单向迁移。 LM 轨道库保留 COLOSSUS 标记,两侧还有其他共同标记和相似文本;这可以来自共同来源、跨线复用或修改记录的保留。相似度 88.06% 本身既不能证明迁移,也不能严格排除独立实现。纸质清单上的装配代号是可见线索;当年具体如何传递版本、是否使用哪一批卡片,仍需历史资料,不能由今天的文本倒推出全部流程。
● 三个数字量三件不同的事,不是三个共享率。 88.06% 和 50.77% 为作者报告、未独立复现,41.39% 可按所列集合大小复算,但集合输入未核实。
● B 类报告占 69%(作者报告,未独立复现)。 其中 95.7%(同为作者报告)的差异字落在 srcsim=1 的块内,只是归一化行序列的一项分组统计,不能读成「95.7% 的差异由地址造成」。
● 固定-固定区不保证同名对象同址。 区域一致率的差别是相关性线索,不能代替对操作数、符号值及编码的逐项分析。
● 前代标记支持谱系联系,不能单独证明完整迁移路线。 不要把相似、同源、未经修改和语义等价混为一谈。
6 源码相同,机器码为什么不同同样的源码行,在不同装配上下文里可能生成不同机器字
本章按同名符号块展示逐字对照,并保留不能解释干净的样本,不拿全映像差异代替具体分析。
源码并没有说谎:它用符号表示对象,机器字则必须按特定工具、布局和编码规则落地。「写法相同」不等于「所有定义相同」,也不等于「执行行为相同」。 本章要做的是区分可由具体操作数说明的差异、统计上碰巧吻合的差值,以及仍然未定的原因;原实验未恢复前,不把它们写成已完成的全量验证。
先打个比方
两座仓库用同一张拣货单:取 A-3、取 B-7、送到 C-1,一个字都没改。可两座仓库的货架排布不一样,同一个 A-3,在甲仓库是进门左手第三排,在乙仓库要走到最里面。单子上看不出区别,走的路却完全不同。 想知道到底差在哪,只能拿两张单子到货架前对着走一遍。
当时的处境
原稿报告清单与映像抽检 400/400 通过,两份文件各 73,728 字节、各有 36 个 Bugger word,汇编零未解析符号、零致命错误。本次未取得原映像、日志和脚本,故不能确认这些测试的输入与覆盖范围。即使报告属实,文件大小与校验字计数也只是格式或构建检查,不等于整份程序正确,更不等于实际执行过任务。 73,728 字节来自现代映像每个 AGC 字保存为 2 字节,对应 36,864 个 AGC 字。
GAMCOMP:84 个字,源码一模一样,机器码 77.4% 相同
源码(两侧逐字相同)
绳芯里的机器码(八进制)
登月舱
指令舱
DLOAD DSU
40145
40145
同
BETAV
02040
02160
异
PDDL BDSU
47441
47441
同
ALPHAM
02070
02310
异
TFF/2
00045
00045
同
STADR
77626
77626
同
STORE TFF
77732
77732
同
(以上为节选,完整 84 字)
规律:只要这一行是「指令」,两侧就一样;只要这一行是「地址」,两侧就不一样。
因为两条船的可写存储里,BETAV 分别放在 E4,1437 与 E4,1557——算法没变,住址变了。
图 5 GAMCOMP 符号块。原报告为 84 字、源码行序列相似度 1.000、机器字一致率 77.4%(以上均为作者报告,未独立复现);19 个差异字中 18 个命中候选位移集合,不等于 18 个均完成实际操作数归因。作者报告·未独立复现 vol4_cases.py(取出的源码行序列相同,机器字不同;按块长排序)
标号 长度 源码相同度 机器码相同度 登月舱地址 指令舱地址
GAMCOMP 84 1.000 77.4% — —
FIGTIME 81 1.000 72.8% — —
COMTERM 70 1.000 67.1% — —
KEPPREP 64 1.000 84.4% — —
FAZA1 59 1.000 66.1% — —
P34/P74E 53 1.000 39.6% — — 原报告中这六个块的归一化源码行序列相同,机器字一致率却为 39.6%–84.4%(作者报告,未独立复现)。 这说明测量所保留的源码信息与最终编码不是同一层面,不是「源码会说谎」。它也不保证这六个块的完整上下文相同,更不能据此判断运行语义相同或不同。
作者报告·未独立复现 vol4_cases.py(GAMCOMP 84 字逐字对照,节选;机器字未重新生成)
GAMCOMP 逐字对照(84 字里挑 13 个位置)
字序 清单里的记号 登月舱 指令舱 原稿解读(仍需编码语境)
0 GAMCOMP VLOAD VSR1 74575 74575 同 ← 指令
1 BETAV 02040 02160 异 ← 地址
2 VSQ SETPD 40236 40236 同
4 NORM ROUND 61501 61501 同
6 PDDL NORM 60325 60325 同
7 ALPHAM 02070 02310 异
12 STODL BETAV 16040 16160 异
13 36D 00045 00045 同 ← 栈里的位置
14 STORE BETAM 02072 02210 异
32 ALPHAV 02032 02152 异
81 STORE FV 02062 02202 异
82 BOV RVQ 43400 43400 同
83 +1 22774 22762 异 ← 跳转目标
对应符号的真实住址(agc_syms.py 查表)
BETAV LM E4,1437 CM E4,1557 差 +80 字
ALPHAV LM E4,1431 CM E4,1551 差 +80 字
ALPHAM LM E4,1467 CM E4,1707 差 +144 字
BETAM LM E4,1471 CM E4,1607 差 +78 字
FV LM E4,1461 CM E4,1601 差 +80 字 节选中,VLOAD VSR1、NORM ROUND、BOV RVQ 的机器字相同,若干涉及命名对象的字不同。BETAV 的编码差 `0o2160−0o2040=80`,与所列地址差相等;ALPHAM 的两项差也都为 144。这些指定名称的局部算术吻合 比「命中任何符号位移」更具体,但仍以作者提供的清单为输入,不是本次独立汇编结果。第 13 字的 `36D` 是十进制数值操作数,必须按解释器寻址约定解读,不能说它「不占存储地址」;表内地址为八进制,位移差为十进制;`+1` 也须联系相对位置和编码规则,不能凭字面归入普通固定地址。GAMCOMP 位于 ORBITAL_INTEGRATION,原稿以 FV 的 PERTURBING ACCELERATIONS 注释关联摄动加速度。全量报告仍保留 :84 字中 65 字相同,18 个差异值命中候选位移集合(原分组为 14 个同 bank、4 个跨 bank),1 个差值 −982 未命中。这里的「65+18=83」不是 83 个字均已完成因果核对;−1024 等差值也不能不经寻址解释就等同于实际跨 bank 引用。
作者报告·未独立复现 脚本 vol4_addrs.py(固定存储符号的地址差异)
ALL3DEC LM F 42,3573 CM F 42,3506 差 0o65 字
WHOLECON LM F 42,3534 CM F 42,3447 差 0o65 字
DMP LM F 03,7103 CM F 03,7052 差 0o31 字
(对照)
MPAC LM E 00154 CM E 00154 同址 原报告中 DMP 入口起址相差 0o31 字,另列两个固定存储符号的地址差。这说明至少应检查固定存储布局,而不仅是可写存储里的变量。一个入口移位不等于整张解释器操作码表整体平移 ,入口地址也不等于解释型操作码的字面编码;更不能由三项地址解释文件级全部 0.9950/0.7545 差异。
作者报告·未独立复现 vol4_cases.py(两种起址下编码相同的样本,不是位置无关性证明)
A 类里「两侧起址不同、却逐字相同」的 55 个符号块(列出较长的 8 个)
DMPNSUB 11 字 LM 03,7316 CM 03,7265
RELTAB 11 字 LM 02,4066 CM 02,4072
MATMOVE 10 字 LM 14,3377 CM 14,3053
MPACVBUF 10 字 LM 03,7532 CM 03,7501
RECAL2 10 字 LM 40,3563 CM 40,3470
VROUND 10 字 LM 03,7140 CM 03,7107
TPSL1 9 字 LM 02,4404 CM 02,4420
VSTORE 9 字 LM 03,6443 CM 03,6412
对照:A 类里两侧起址也相同的块(同时满足同址与同字,不是因果证明)
GENDDV 16 字 两侧都在 00,2570
TSSL 13 字 两侧都在 00,2101
V/SCDV 11 字 两侧都在 00,2750
MPACSRND 8 字 两侧都在 00,2050 这是两种布局下的观察,不是充分的反向验证。 MATMOVE 起址不同而编码相同,不证明它内部没有绝对引用:被引用的目标可以没动,某些编码也可能不受此次变化影响。GENDDV 等同址块的机器字相同,同样是观测事实,而非「只要同址就理所当然同字」。由于样本本来就是按 A 类同字条件选出的,不能再用这些样本排除全部汇编器差异、块外定义变化或未被提取的源码差异。
作者报告·未独立复现 vol4_delta.py + vol4_perm.py(B 类差异字分组、候选差值匹配及置换检验)
B 类报告为 1,037 个符号块,共 4,706 个差异字
第一步 描述性分组(不是成因分组)
被提取的归一化源码行序列一致(srcsim = 1.000)
1,025 个块 4,502 个差异字 (95.7%)
→ 只说明测量保留的源码行一致;仍须检查符号定义、
SETLOC /BANK /EBANK、伪指令/宏式展开、块外上下文和工具行为
源码有少量改动(0.95 ≤ srcsim < 1.0)
12 个块 204 个差异字 (4.3%)
→ 存在可见文本差异;KEPCONVG 的局部反例见下一项
第二步 候选差值匹配(vol4_delta.py,未逐字确定实际引用目标)
原方法称:差值 = CM字 - LM字(按 15 位有符号数;具体转换待脚本确认),
查是否等于位移集合中的任一值,而非该操作数实际符号的位移。
同 bank 候选位移口径 3,964 字 84.23%
放宽候选集合(含跨 bank 线性位移) 4,384 字 93.16%
对不上(其余) 322 字 6.84%
同一套方法用在 srcsim=1.000 那组上 4,232 / 4,502 (94.00%)
第三步 置换检验(vol4_perm.py,10,000 次,固定种子 19690720)
检验一 原稿称重排 CM 各 bank 的偏移后重算位移集合:
打乱后仍有 87.60% ± 1.64% 能「碰上」(放宽口径 91.63% ± 1.33%)
同 bank 口径实测值低于该零模型;高重叠本身不能充当归因证据
(旧的「随机概率 0.7%」是均匀假设下的算法,错得离谱)
检验二 原稿称将差异字换成「无关布局的差值」:
无关布局的差值只有 29.04% ± 1.07% 碰上真实集合
(放宽口径 34.58% ± 0.98%)
实测 84.23% / 93.16% —— 10,000 次置换里 0 次达到实测值
差值直方图前几名(原稿称这些数值也见于符号位移;非实际引用映射)
+36 641 字 (13.6%)
-25 413 字 ( 8.8%)
+2 264 字 ( 5.6%)
+146 120 字 ( 2.5%)
+80 83 字 ( 1.8%) ← 也见于 ALPHAV / BETAV / FV 的所列位移
前 40 个差值覆盖 71.95% 的差异字 原稿保留了一个重要的失败结果:候选集合很容易命中。 其置换报告中,同 bank 口径随机重排后的命中率为 87.60%(作者报告,未独立复现),高于实测 84.23%。注:置换检验中候选集合已饱和(随机重排基线 87.60%),实测命中率不高于随机重排基线;该检验只支持值对齐,不支持逐字归因。图中数字为作者报告,未独立复现;放宽口径为 91.63%,与 93.16% 接近(此三数均为作者报告,未独立复现)。它削弱了「命中就说明地址成因」的说法。另一个零模型报告 29.04%/34.58%(作者报告,未独立复现),10,000 次未达到实测;这最多描述该零模型下的差异,不能证明实际差异由地址引起,更不能推出迁移方式或算法未变 。若只是把集合元素换顺序,集合本身不会改变,故置换对象、重新计算方法、独立单位和零假设必须公开。`95.7%` 也只是 srcsim 分组比例;匹配上的字仍未必得到归因,没匹配上的 6.84% 也不能直接叫「真改动」。AGC 采用反码数值表示,原脚本所谓「15 位有符号差」的转换与回绕方式还须核对,不能默认现代二补码差值具有地址意义。
作者报告/源码核对 KEPCONVG 反例:存在可见源码差异;vol4_delta2.py 的机器字统计未复现
KEPCONVG 开普勒收敛迭代 n=53 字 源码相同度 0.962
LM 12,2333 CM 12,2346 (同一 bank,所列入口起址相差 11 字)
7 个差异字逐个看:
第28字 LM 11033 -> CM 11606 差 +363 候选地址差(作者配对)
← D1/128 这个常数在两条船上是 4,3032 -> 4,3605,位移正好 +363
第43字 LM 11047 -> CM 11622 差 +363 候选地址差(作者配对)
← D1/256 同上,4,3046 -> 4,3621,位移也是 +363
第24字 LM 14043 -> CM 16655 差 +1418 RCNORM 引用,不能直接定为「非地址」
第35字 LM 00043 -> CM 02655 差 +1418 同上
第41字 LM 00043 -> CM 02655 差 +1418 同上
← 三处都是 RCNORM 这个名字。
LM 实际定义为 RCNORM EQUALS 34D(数值 0o42),
CM 定义为 RCNORM EQUALS URRECT +6(原报告地址 E5,1654)。
数值化符号不等于固定存储常量;必须按解释器寻址规则解读。
第51字 LM 01553 -> CM 35553 差 +14336 可见源码编码形式不同
LM: STORE XPREV CM: STCALL XPREV
第52字 LM 77650 -> CM 02270 差 +1296 可见源码编码形式不同
LM: GOTO CM: KEPRTN
← LM 收尾 STORE XPREV / GOTO / KEPRTN,CM 为 STCALL XPREV / KEPRTN。 反例要保留,但解释必须修正。 前两项按原表与 D1/128、D1/256 的地址差相合,机器字尚未独立生成。RCNORM 的三项不能再称为「LM 固定常量、CM 可写变量」:本次核对到 LM 的 `EQUALS 34D` 与 CM 的 `EQUALS URRECT +6`,且两侧都执行 `STODL RCNORM` 保存运行时结果。这里涉及解释器操作数编码和存储安排,`C 00042` 的工具分类不等于固定存储地址。末尾的 STORE/GOTO 与 STCALL 组合确有文本区别,但 `KEPRTN` 是转移目标符号,不能说「GOTO 这条指令改成了 KEPRTN」,也不能仅凭编码形式判断轨道算法或外部行为改变。这个例子足以反驳「所有块源码都没改」,却还不足以把七个字准确分成两个地址变化和五个非地址变化。
作者推导 这一章能证明什么,不能证明什么
本次能够核对或限定的内容:
· 六个块的相似度与机器字一致率是作者报告,未独立重跑
· GAMCOMP 的部分指定符号差值可手算吻合;18/19 仍是候选集合命中
· 55 个异址同字块是有限样本,不证明位置无关,也不排除工具差异
· DMP 等起址及解释器文件得分为原报告,不能代表整张操作码表平移
· 95.7% 是差异字所在块满足 srcsim=1 的分组比例,不是地址归因比例
· RCNORM 的两侧定义和 KEPCONVG 收尾差异可在 raw 源码中定位
· 置换报告的 84.23% 对 29.04% 依赖所选零模型,不能推出因果
· 10,000 次未命中不表示概率为零;缺脚本不能核验检验有效性
· 候选集合的高重叠是已在原报告中承认的方法限制
不能证明:
· 原实验的精确版本、筛选全集、全部机器字及各项比例是否可复现
· 每个差异字的实际操作数与地址、数值、指令形式或上下文各占多少
· 相同或不同机器字在实际飞行中是否表现为相同行为(未做任务仿真)
· 当年是否有人专门评估过这个差异(没有找到 1960s 文档) 把边界写出来,比漂亮的归因更重要。 这里保留的是待复现的静态比较报告和若干本次核对的源码文本;不能统称为已经核验的绳芯事实。机器字相同也可能因输入、bank 状态或外设不同而行为不同,机器字不同也可能实现相同功能。
● 源码、机器字与执行语义是三个层面。 符号定义、布局、工具和运行环境必须分别检查。
● 撤回「95.7% 的差异只来自符号表」的断言。 它仅描述所取源码行序列相同的分组,块外装配上下文并未被排除。
● 命中任何候选位移不等于匹配实际操作数。 集合饱和尤其会让命中率产生误导,不能把 84.23% 或 93.16%(作者报告,未独立复现)当归因正确率。
● 置换检验不是因果证明。 不同零模型给出不同基线,须公开完整算法、输入与检验单位;当前仅保留作者报告。
● 异址同字样本不排除其他解释。 位置无关、汇编器差异、控制流等价与整体算法是否改变,都不能由这组样本直接判定。
7 两套传感器两种世界硬件接口不同,会影响可共享的边界
轨道数学、调度和解释器等较通用层有复用线索;贴近传感器与执行机构的层更可能分化。但这不是「抽象层必然完全相同、硬件层绝不能共用」的定律:接口代码也可能共享部分算法或结构,需要具体看对应关系。
先打个比方
两家餐厅可以共享采购、记账和排班办法;燃气灶与电磁炉的火力控制则需适配。适配未必等于全部重写,也可能是保留共同控制思想,替换直接驱动设备的部分。
当时的处境
三组对照呈现的是相近需求、不同设备或接口 :光学瞄准有 AOT 与 SXT;推力控制两边都调整推力轴,但机构、配平、节流和反馈安排不同;AGS 初始化则只服务登月舱的备份系统。不能用「一个转喷管、一个转发动机」制造并不存在的两类原理。
同一件事,两套硬件,两套代码
要解决的问题
登月舱怎么解决
指令舱怎么解决
看星星,校惯性平台
AOT 对准光学望远镜
SXT 空间六分仪
AOTMARK.agc 616 行 │ SXTMARK.agc 613 行 │ 同名例程 VACSTOR:源码相似 0.074,机器码相似 0.000
控制推力指向
配平万向节+节流阀
SPS 摆动喷管(TVC)
登月舱 2 个文件 740 行 │ 指令舱 7 个 TVC 文件共 2,492 行 │ 差 3.4 倍
主机之外的第二条路
AGS 备份制导(另一台计算机)
(没有对应模块)
AGS_INITIALIZATION.agc 213 行,R47——登月舱要持续给另一台计算机喂状态向量
这三行是同一条规律:贴着硬件的那一层难以直接共用;抽象层相同的东西可以共用。
反过来,凡是两侧能共用的部分(轨道数学、解释器、自检),恰恰是硬件无关的部分。
图 6 三组接口案例——光学瞄准、推力控制与 AGS 初始化。前两组对照不同设备下的相关需求,第三组为登月舱单侧接口,不能都称为「同一个需求、两套硬件」;直接依赖设备的实现需要分别检查。源码实证 Luminary099/AOTMARK.agc:169-171 / :206-207 / :573(登月舱,616 非空行)
# THE OPTAXIS SUBROUTINE COMPUTES THE X AND Y MARK PLANE VECS AND
# AND ROTATES THEM THRU THE APPARENT FIELD OF VIEW ROTATION UNIQUE TO AOT
# OPTAXIS USES OANB TO COMPUTE THE OPTIC AXIS
# THE OANB SUBROUTINE COMPUTES THE OPTIC AXIS OF THE SIGHTING INSTRUMENT
# FROM AZIMUTH AND ELEVATION INPUT FROM THE ASTRONAUT.
# MARKTYPE TESTS TO SEE IF LEM ON LUNAR SURFACE. IF IT IS RETURN TO LOC+1 登月舱使用 AOT(Alignment Optical Telescope,对准光学望远镜) 。注释中的 UNIQUE TO AOT 指出该视场旋转处理具有设备特定性;`MARKTYPE` 还检查是否处于月面状态。后一条件关联登月舱任务,不宜夸写成「指令舱永远不会停在任何表面上」。
源码实证 Comanche055/SXTMARK.agc:39-41(指令舱,613 非空行)
# PROGRAM NAME - SXTMARK DATE - 5 APRIL 1967
# PROGRAM MODIFIED BY 258/278 PROGRAMMERS LOG SECTION SXTMARK
# MOD BY - R. MELANSON TO ADD DOCUMENTATION ASSEMBLY SUNDISK REV. 116 指令舱使用 SXT(Space Sextant,空间六分仪) 。注释的 5 APRIL 1967 表明这份记录可追溯到较早时期,不证明整个模块在那天定版;ASSEMBLY SUNDISK REV. 116 是指令舱程序线关联的线索。当前 LM 树使用 AOTMARK,不足以证明 SXTMARK 的任何代码在全部历史版本中都「从未进入登月舱线」。
作者报告·未独立复现 脚本 vol4_cases.py(同名符号块 VACSTOR 的逐字比对)
VACSTOR 长度 27 字
源码相同度 0.074
机器码相同度 0.000
登月舱:aotmark / 指令舱:sxtmark 原报告的 VACSTOR 配对长 27 字,相同字数为零。 两文件非空行数 616 与 613 接近,只能说明本统计口径下文本规模接近,不能量出问题难度相同。设备差异能从相关接口代码寻找解释,但不能由这 27 字推出整文件的视场、坐标变换、误差处理都无共享。VACSTOR 有同名对应,按源码相似度 0.074 属于 C 类;它不是「代码无对应」的 D 类。
作者报告·未独立复现 脚本:推力控制文件规模对比(非空行)
指令舱(7 个 TVC 文件,合计 2,492 行)
TVCDAPS.agc 661 TVCROLLDAP.agc 541 TVCINITIALIZE.agc 347
TVCRESTARTS.agc 247 TVCEXECUTIVE.agc 241 TVCSTROKETEST.agc 230
TVCMASSPROP.agc 225
登月舱(2 个文件,合计 740 行)
TRIM_GIMBAL_CONTROL_SYSTEM.agc 537
THROTTLE_CONTROL_ROUTINES.agc 203 两边都调整发动机推力轴,但原稿选取的文件范围不同。 CM 的 TVC 文件涉及姿态控制、初始化、重启、质量特性和测试;LM 这里仅列配平与节流两文件,其姿态控制和服务代码还分布在其他模块。因而 2,492 对 740 首先是选取范围内的非空行比较,不能当成被控对象复杂度的直接映射,更不能凭行数断定哪边需要考虑的物理问题更多。
● 光学设备为 AOT 对 SXT。 同名块 VACSTOR 的 27 字零一致为作者报告,是局部 C 类差异,不是整体无复用的证明。
● 推力控制的选取范围不对称。 2,492 对 740 是非空行比,不等于复杂度、投入或执行耗时比。
● 登月舱有 AGS 初始化接口。 R47 按操作更新状态数据;它不证明持续镜像或无缝接管。
● 跨机型适用性写在选项代码表中。 本册所引是 OPTION CODES FOR 504,不是扩展动词号表。
8 任务当天两台机器各自做什么同一天,一个在下降,一个在绕行
前面主要是静态比较,本章把它们放回 1969 年 7 月 20 日的任务场景。两台机器承担不同工作,但本册没有两侧处理器负载曲线,不能说当时两台都在满负荷运行 。
先打个比方
菜谱能告诉你这道菜怎么做、放多少盐,但它说不出那天客人几点进门、点了什么、哪道菜退了。想知道那天发生了什么,得翻流水账,不是翻菜谱。 源码是菜谱,任务记录是流水账——两样都有用,不能互相冒充。
当时的处境
这一章得先分清两类证据:「某个程序做什么」能从源码读出来,是源码实证;「那天几点几分发生了什么」属于任务历史,只能引用外部资料并明确标出。下面会分开标注,不混在一起。
源码实证 Luminary099/EXECUTIVE.agc:152 / 213(1201 与 1202 告警码的定义)
OCT 1201 # NO VAC AREAS.
OCT 1202 1202 对应执行程序无法取得 core set(核心集、任务工作区) ,1201 对应 VAC 区不足;原行号只作定位线索。它们是资源分配失败告警,不是 CPU 利用率的直接读数。出现告警后进入软件报警/重启恢复路径,哪些工作恢复取决于重启保护、阶段表等机制,不能简化成「自动找出优先级最低的任务扔掉」。两侧 EXECUTIVE 都定义这些告警,但行号差一行既不说明之前只增删过一行,也不保证调用序列完全一样。
源码实证 两侧 ASSEMBLY_AND_OPERATION_INFORMATION.agc(告警表对照)
登月舱(Luminary099,第 975-976 行)
# 01201 * EXECUTIVE OVERFLOW - NO VAC AREAS EXEC
# 01202 * EXECUTIVE OVERFLOW - NO CORE SETS EXEC
指令舱(Comanche055,第 964-965 行)
# 01201 * EXECUTIVE OVERFLOW - NO VAC AREAS EXEC BAILOUT
# 01202 * EXECUTIVE OVERFLOW - NO CORE SETS EXEC BAILOUT CM 的表有 ALARM ROUTINE 列,01201/01202 填的是 BAILOUT;LM 这两项没有该列内容,但不能据此推断没有相同类型的恢复路径。 本次核对 EXECUTIVE:LM 在 1201/1202 前调用 `BAILOUT1`,CM 调用 `BAILOUT`。LM 的 ALARM_AND_ABORT 中,BAILOUT1 经 ADR40400 接到与 BAILOUT 相关的后续处理;LM 告警表星号说明也写着软件重启。入口准备和具体恢复细节不能一概视为完全相同,但「LM 丢任务继续、CM 选择放弃」的对比没有得到这张表的支持,予以撤回。
外部资料·本次未逐秒复核 作者据 NASA TM X-58040 表 IV(文献 6)、Mission Report 表 5-I(文献 7)、ALSJ(文献 8)整理
1969-07-20 GET(Ground Elapsed Time,任务经过时间;时:分:秒)
102:33:05 下降发动机点火(PDI),进入 P63 制动段
102:38:22 第一次 1202 告警
102:41:32 自动转入 P64 接近段
102:43:09 落点重新指定(Armstrong 手动推移着陆点)
102:43:22 手动转入 P66 下降率控制
102:45:40 原表所列着陆时刻(触地与发动机关机的精确区分待原记录核对)
102:45:58 “Houston, Tranquility Base here. The Eagle has landed.”
转入 P64 那一刻:高度 7,129 ft,下降率约 125 ft/s
转入 P66 后 4 秒的通话(102:43:26):「400 feet, down at 9」
接近段延伸到约 500 ft;若不手动接管,P65 会在约 150 ft 自动接手
全程共 5 次告警:4 次 1202 + 1 次 1201(后者在 102:42:18)
同一时段,指令舱 Columbia 由 Michael Collins 独自驾驶,
在月球轨道上绕行等待。 时间线按原稿保留,性质是作者据文献整理的外部史实,不是源码推算,也不是本次重新逐秒复核的结果。 P63/P64/P66 的任务角色可结合源码理解,但 `P66 ERASABLES (R.O.D.)` 单独只标识下降率相关工作区,完整控制分工还需读程序。102:45:40 与 102:45:58 按所列数字相差 18 秒;触地、接触灯、发动机关机与通话可能是不同事件,不能把它们混成同一时刻,也不能没有记录就替这 18 秒编排机组动作。约 500 ft、约 150 ft 等描述也要区分设计切换条件与当日实际轨迹。
源码实证 Luminary099/ERASABLE_ASSIGNMENTS.agc:801 / :2111 / :2608 / :2612
# P63, P64, P65, P66, AND P67. (1D)
# P63 AND P64 CONSTANTS. -PAD LOADED- (4D)
# P66 ERASABLES (R.O.D.) (1D)
# P66 ERASABLES (R.O.D.) (14D) 源码实证 登月舱打印清单第 739 页,原图注定位到 `P63IGN`,并摘录 `MAKE SURE DAP IS NOT IN MINIMUM-IMPULSE MODE, IN CASE OF SWITCH TO P66.`。它体现对可能切换 P66 的准备,不是当日切换时刻的证据。页底 ZOOM RESTART 入口原定位为 `BURN,_BABY,_BURN_--_MASTER_IGNITION_ROUTINE.agc:455-491`;图像与旧行号本次未复核。PAD LOADED 表示这些量属于预置装载的数据,而非此处固化在绳芯内的常数。 仅凭这个标记,不能确定某一数值由谁计算、何时装载、是否通过上行链路装入,更不能据此解释任务当天的 Go 决策。把可变任务数据放在可擦除存储是一种配置方式;1201/1202 后能否继续,还需要当时的告警知识、重启表现、飞行状态和地面/机组判断等独立证据。
● 1202 的源码含义可查 :无可用 core set;1201 为无可用 VAC 区。告警出现与具体时刻则要查任务记录。
● 不能拿告警表列数推断处置策略。 LM 调用 BAILOUT1,CM 调用 BAILOUT,均涉及报警/软件重启路径;这不等于恢复全过程毫无差别。
● PAD LOADED 只支持预置数据属性。 不自动证明上传时间、装载渠道或它是 Go 决策的直接前提。
● 本章的时间线属于外部资料 ,不是源码证据;源码可用于理解程序及其行为,不能单靠它确定任务当天的实际执行时刻。源码里的编写或清单日期也不是飞行事件时间戳。
9 后记:1969 到今天一个软件家族,是怎样留下可追查线索的
原稿用 177 个文件实例、1,502 个可比符号块和 17,681 个字组织比较;这些规模仍待原统计版本与工具补齐。更稳妥的问题是:两个任务不同的产品,怎样保留共同基础,又容纳各自的变化。
当时的处境
纸面和转录文本留下多种工程控制线索:清单的装配标记、集中的变量定义、选项代码的适用性、旧版本的注释。它们使今天仍能追问家族关系;但本册未查遍当年的流程记录,不能由几项线索概括完整配置管理制度或团队分工。
源码线索 四个家族共用候选文件的共同标记
CONIC_SUBROUTINES.agc 轨道数学 两侧都写 COLOSSUS REVISION 88
IMU_MODE_SWITCHING_ROUTINES.agc 平台模式切换 两侧都写 SUNDISK REV. 82(LM:765 / CM:763)
WAITLIST.agc 定时任务调度 两侧都写 SUNBURST REV 5
AGC_BLOCK_TWO_SELF-CHECK.agc 机器自检 两侧都写 UTILITYM REV 25 这些候选文件有共同来源与平台背景,并非完全「与硬件无关」。 轨道数学较通用,调度依赖 AGC 的执行环境,自检直接检查机器,惯性平台模式切换也接触硬件接口。共享平台能使部分实现复用,设备差异则可能要求适配或重写。能否复用,要看接口、数据约定和具体实现;抽象层选择很重要,但不是唯一因素。
作者报告·未独立复现 vol4_addrs.py(共同符号同址/异址统计,不直接代表设计分层)
可擦除存储共同变量 476 个
同址 87 个 (18.3%) 例:MPAC E00154、ADIAX/ADIAY/ADIAZ、AZO/AXO、CDUIND
异址 389 个 (81.7%);其中同 bank 的 319 个:偏移绝对值中位数 23 字、最大 198 字 18.3% 同址是对原报告输入的比例表达。 MPAC 等例子提示某些共同工作区布局稳定;其余 389 个异址符号是否集中于任务专属层,尚缺完整映射。变量表还有固定位置、别名与覆盖区,不能仅凭排列前后推断模块边界。某个分配变化可能影响依赖它的后续定义,但不一定影响全表;0.3039 的文本相似度也不是这种因果链的独立证明。
源码实证 Comanche055/ASSEMBLY_AND_OPERATION_INFORMATION.agc:1038-1045
# 00004 SPECIFY RADAR 1=RR 2=LR R04 SUNDANCE + LUMINARY
# 00005 SPECIFY SOR PHASE 1=FIRST 2=SECOND P38 COLOSSUS + LUMINARY
# 00006 SPECIFY RR COARSE ALIGN OPTION 1=LOCKON 2=CONTINUOUS DESIG. V41N72 SUNDANCE + LUMINARY
# 00007 SPECIFY PROPULSION SYSTEM 1=SPS 2=RCS P37 COLOSSUS
# 00010 SPECIFY ALIGNMENT MODE 0=ANY TIME 1=REFSMMAT +G P57 LUMINARY
# 2=TWO BODIES 3=ONE BODY + G
# 00011 SPECIFY SEPARATION MONITOR PHASE 1=DELTAV 2=STATE VECTOR UPDATE P46 LUMINARY
# 00012 SPECIFY CSM ORBIT OPTION 1=NO ORBIT CHANGE 2=CHANGE P22 LUMINARY 这张选项代码表把用途、输入值、程序和适用性并列记录。 它像今天跨产品共享的一份接口约定,但「注册表」只能作类比,不能据此断定当时没有中央版本存储,或已经知道由哪个团队负责。现代工具可以保存约定,仍不能代替对产品差异的明确说明。
作者推导 这一册的方法,可以迁移到哪
这一册用的四层比较不是为阿波罗定制的,
任何「共同平台上的多个产品」都可以借鉴,但须按材料调整:
① 文件层 看组织范围 ② 模块层 查谱系线索(历史版本、原件及可靠提交记录相互印证)
③ 接口/控制流层 看相近任务的实现 ④ 机器字层 查具体编码,再另行验证运行语义
以及一条筛选原则:只比较能回答一个工程问题的差异。
第 192 行不一样 —— 不写。
为什么两边都要做测量融合、测量来源却不同 —— 写。 比三个相似度数字更有价值的,是可追查的记录。 版本标记、变量定义、选项适用性和 PAD LOADED 让后人知道下一步去哪里核对。五十七年后仍能读出这些关系,值得珍惜;但不能因此说完整谱系已经理清。要让研究真正可复现,今天还应留下源码提交号、脚本、工具版本、输入输出及明确的证据边界。
● 复用依赖共同约定、平台与合适的抽象。 四个候选文件的硬件依赖程度不同,不能把它们归为一种纯数学共用层。
● 同址/异址统计不能直接还原设计分区。 18.3% 与 81.7% 是作者报告;位移集合检验也不能证明某个布局变化导致全部后续变化。
● 选项代码表留下跨产品约定。 它可类比接口登记表,但不是已还原的维护组织或完整治理制度。
● 收在这里 :两套软件保留共同基础,也为任务与设备差异作出不同安排。数学库有同源线索,变量定义有差别,部分任务模块各自出现;不再概括成「数学照搬、其余只改地址」。
本册的观察路径是:共同平台 → 共享线索 → 任务与接口差异 → 单侧或分化模块 → 布局与编码比较 → 两个软件产品。箭头组织阅读,不代表每一步因果都已证实。
真正值得问的从来不是「我们有什么不同」,而是:什么值得共享?什么应该分开? 这是 1969 年的问题,也是今天的问题。
怎么复核本册的每一条 下面几条命令可以直接粘贴执行。原始源码属公有领域,任何人都能拿到同一份底本。
1. 取两份源码(Virtual AGC 维护版,可干净汇编;本册的文件名与行号都以它为准)
git clone https://github.com/virtualagc/virtualagc
cd virtualagc
# 先取得并检出作者原实验的完整 Virtual AGC 提交号(原统计版本待补)。
# chrislgarry/Apollo-11 的 911e5c0 属于另一仓库,不能当作本树版本。
# 文件名、转录修订和行号都可能不同;按文件名与原文锚点定位。
2. 按所选版本的 yaYUL 构建说明先构建工具,并记录版本、编译器和参数。
# 以下仅在仓库根目录下已有可用的 yaYUL/yaYUL 时适用(类 Unix shell):
(cd Luminary099 && ../yaYUL/yaYUL MAIN.agc > lum.lst 2> lum.err)
(cd Comanche055 && ../yaYUL/yaYUL MAIN.agc > com.lst 2> com.err)
# 必须检查退出状态、错误日志、实际输出名与清单格式;Windows 可执行文件名可能不同。
3. 下面是原稿引用的脚本清单;本次均未提供,不能把它们当成可运行交付物:
# vol4_matrix.py 文件名、非空行与文件级相似度
# vol4_binary.py 映像检查及符号块级比较(不是任务执行)
# vol4_cases.py 样本、归一化行序列与机器字相似度
# vol4_addrs.py 符号取值/地址分类与差值
# vol4_select.py 原 A/B/C 分类及边界情况
# vol4_delta.py 候选位移集合命中(不是已完成的因果归因)
# vol4_perm.py 置换对象、零模型和检验过程
# vol4_table.py 比较矩阵;vol4_delta2.py 则被原稿用于反例分析
4. agc_syms.py 原稿用于查询 BETAV、MPAC、DMP 等符号,脚本也待补。
# 本次不宣称已运行以上构建或脚本,也未生成原实验的清单或映像。
· **原统计版本待补。**需要原源树提交号及修改记录、`vol4_*.py`/`agc_syms.py`、yaYUL 版本与参数、原清单/映像/日志和校验摘要;仅有新快照不能补上原实验的可复现性。73,728 字节、36 个校验字和 400/400 等仍是作者报告。
· **引用仓库统一为 Virtual AGC。**原行号是定位线索,不再套用另一仓库的 `911e5c0`。行号变化时用标号、注释及历史页面定位;新快照核对与原实验复现须分开登记。
· **外部资料需按编号查原文。**本次未逐页核对扫描图与任务报告,也未逐秒核对时间线,不把保留引用视为完成验证。
· **算术复算不等于实验复现。**本次纠正集合分母等可直接计算的问题;实际样本是否正确还要回到原文件与脚本,不能说任何新跑出的不同结果都自动更正确。
· 「解释性类比」只是解释工具,不是证据,不必去源码里找。
[1] Virtual AGC 源码树:Luminary099(登月舱)/ Comanche055(指令舱)
Ron Burkey 等(Virtual AGC 项目整理),MIT Museum 藏硬拷贝数字化(Paul Fjeld 扫描) · 源码
https://github.com/virtualagc/virtualagc,使用 Luminary099/ 与 Comanche055/ 两个目录。所引源码文件头标注 Public domain。本册源码引用以此仓库的文件命名为准,原统计版本待补 ;原行号不能据此保证与当前树一致。
用于:全文所有「源码实证」条目的出处,以及第 0 章两份硬拷贝题头的转录。
[2] 同一份程序的另一份公开副本(chrislgarry/Apollo-11)
chrislgarry(整理);原稿另列 commit `911e5c0283c629c50cb97666f34065e8c07d71a5`,本次未核实该提交的日期与内容,也不将它用于文献 [1] 的版本锁定。 · 源码
https://github.com/chrislgarry/Apollo-11。这是相关程序的另一整理副本,不应默认其内容与 Virtual AGC 逐行相同;文件名、行号和转录修订须分别核对。
用于:提醒读者:核对行号要认准文献 1 那棵树。
[3] chrislgarry/Apollo-11 仓库 README 的 Attribution 表与源码头部注记(来源与清单时间)
virtualagc/virtualagc 仓库 README · 源码
Attribution 表在 chrislgarry/Apollo-11 的 README(本次逐字核对);virtualagc 仓库自身 README 无此表。版本与日期另经文献 [1] 两侧 ASSEMBLY_AND_OPERATION_INFORMATION.agc 的 Notations 段,读到 LM 的 `Assemble revision 001 ... LMY99 ... 2021112-061`、`16:27 JULY 14, 1969` 与 CM 的 `10:28 APR. 1, 1969`。README 本身本次未另行比对。
用于:硬拷贝题头的版本标识、文件号与清单时间;不用于确定软件冻结、绳芯制造、装订完成或装船日期。
[4] Apollo GN&C System Components(Appendix F)
NASA / MIT · 一手技术报告
NASA NTRS 20230005922(NASA/TP-20230005922,2023),Appendix F 取自 Draper Lab Report R-700;p288 含 AGC「general purpose computer…priority driven operating system」原话,p292(印刷页 271)含 AGC 规格表——均已对页核验。原稿在本条误引 NTRS 19690010164(该号实为 SP-8015 再入飞行器导航专册,与 AGC 无关),已更正。
用于:Block II 存储规格与字格式。36,864 字固定存储、2,048 字可擦除存储;通常按每字 15 位信息加 1 位奇校验描述。约 11.72 微秒是存储周期(MCT),不能笼统写成每条指令的周期,指令需若干 MCT。报告页码与这些规格的逐项对应本次未复核。
[5] Virtual AGC 项目:yaYUL 汇编器与 yaAGC 模拟器
Ron Burkey 等,开源项目 · 公开网页
github.com/virtualagc/virtualagc;项目网站 virtualagc.github.io/virtualagc/ 与 ibiblio.org/apollo。chrislgarry/Apollo-11 仓库 README 的 Attribution 表里,Assembler 一栏写的就是 yaYUL(2026-09-15 对其 raw README 逐字核对)。
用于:源码汇编与模拟器的工具入口。原稿所报两份 73,728 字节映像及各项比对仍待补工具版本和产物;汇编与静态比对不是 yaAGC 任务仿真的替代。
[6] Apollo Lunar Descent and Ascent Trajectories(NASA TM X-58040)
Floyd V. Bennett,NASA Manned Spacecraft Center, Houston · 一手技术报告
NASA 技术备忘录,1970 年 3 月,报告号 NASA-TM-X-58040,NTRS 19700024568(入藏号 70N33879)。原为 AIAA 第 8 届航天科学会议论文,1970 年 1 月 19–21 日,纽约。本册用的是它的表 IV(Lunar Descent Event Times)。
用于:第 8 章时间线的主源:各事件时刻、5 次告警的次数与代码、以及转入 P64 那一刻的高度与下降率。
[7] Apollo 11 Mission Report(MSC-00171 / NASA-TM-X-62633)
NASA Manned Spacecraft Center, Mission Evaluation Team · 一手技术报告
1969 年 11 月,NTRS 19700008096(入藏号 70N17401;另有一份扫描件编号 19710015566)。本册用的是第 5 部分表 5-I。
用于:原稿称与文献 [6] 交叉印证时间线,并给出制动/接近段划分、高门高度 7,129 ft、下降率 125 ft/s 等。设计界限与当日事件实测值须分开;本次未逐页复核。
[8] Apollo 11 Lunar Surface Journal(空地通话记录与 Program Alarms 条目)
NASA 历史部(ALSJ) · 史料 / 综述
nasa.gov 历史档案,含逐秒空地通话誊本与当事软件人员对 1201 / 1202 的回顾。
用于:原稿的两处旁证:① 102:43:26 的「400 feet, down at 9」通话;② 1201/1202 与 core set、VAC 区耗尽的关联。通话时刻本次未逐秒复核,不能只靠一句通话反推精确的程序切换高度。
本册的行号以哪棵树为准。 本册所有「源码实证」的文件名与行号,都以 virtualagc/virtualagc 仓库里的 Luminary099/ 与 Comanche055/ 两个目录为准(见文献 [1])。网上更常见的另一份副本 chrislgarry/Apollo-11 (commit 911e5c0,2026-07-15 提交)是同一份程序的另一个整理版:它把文件名里的逗号换成了下划线(如 P37,P70.agc 变成 P37_P70.agc),行号也整体不同——原稿关于两边同名文件无一逐行相同的全称断言未附比较清单,此处不再保留。因此不要拿那份来核对本册行号;定位以标号与注释锚点为准。 源码自身的装订记时 16:27 JULY 14, 1969(登月舱)与 10:28 APR. 1, 1969(指令舱),是印在硬拷贝原件上的时刻,与任何仓库的提交时间无关,两者相差 57 年。
术语速览 读正文卡住的词,这里一句话讲清
AGC Apollo Guidance Computer,阿波罗制导计算机。此处比较指令舱与登月舱的 Block II 计算平台,不指任务里的所有计算机。 Luminary 登月舱飞控软件的程序名。阿波罗 11 号用的是 Luminary 1A,内部版本号 099。 Comanche 指令舱飞控软件的程序名。对外又称 Colossus 2A,内部版本号 055。 LVDC Launch Vehicle Digital Computer,IBM 研制的运载火箭数字计算机,位于 S-IVB 上方的仪器舱;它不是 AGC,也不是登月舱的 AGS。 字(word) AGC 的基本存储单位,通常为 15 位信息加 1 位奇校验;运算寄存器的位定义另有细节。AGC 的字寻址不等于现代 8 位字节寻址。 绳芯存储(core rope) 以穿线方式编码的固定存储。36,864 个 AGC 字;现代映像若每字占 2 字节,文件为 73,728 字节,即 72 KiB,不应把映像字节数直接叫 AGC 字数。 可擦除存储(erasable) 可读写内存,即今天的 RAM。只有 2,048 字,是最紧的资源。 bank 存储分区。固定存储为 36 个各 1,024 字的 bank;可擦除存储分区大小不同。固定-固定区的寻址窗口无需 bank 切换,但不保证两版同名对象同址。 E-bank 可擦除存储的分区 E0–E7,每区 256 字;部分区域直接可寻址,其余经切换窗口访问。分区号与窗口偏移要一起解释。 DSKY 显示与键盘组件,宇航员和计算机说话的那块面板。两条船用的是同一型硬件。 解释器(Interpreter) 用 AGC 基本指令实现的软件,读取解释型操作码并调用相应处理流程,支持向量、多精度等运算;不是把每条解释指令现场编译成新机器码。 MPAC MULTI-PURPOSE ACCUMULATOR,多功能累加器。解释器做算术的地方,只占 7 个字。 AOT Alignment Optical Telescope,对准光学望远镜。登月舱上用来看星星定姿态的设备。 SXT Space Sextant,空间六分仪。指令舱上同类设备,结构不同。 TVC Thrust Vector Control,推力矢量控制。此处主要以发动机万向支承/作动器调整推力轴方向;LM 与 SPS 都涉及该功能,具体控制实现不同。 AGS / AEA AGS 为登月舱中止制导系统;AEA 是其中的计算电子组件。R47 可初始化/更新其状态数据,不代表与主 AGC 持续镜像。 装配标记(assemble revision) 硬拷贝清单上的装配修订标识。需区分程序 build、清单修订、打印时间与飞行软件冻结日期,不能互相替代。 【补充】符号块 本册按符号边界取出的比较单元,可能包含例程、入口片段或数据表;同名不保证功能和边界相同。 【补充】时钟 / MCT / 指令 约 1.024 MHz 的时序脉冲不等于每秒执行约一百万条指令;约 11.72 微秒为一个存储周期,指令需若干存储周期,解释型指令还包含软件执行开销。
证据来源。 源码实证来自本地两份源码树(Virtual AGC 维护版 Luminary099 / Comanche055,源自 MIT 博物馆藏硬拷贝数字化,公有领域),均标注文件与行号。原稿报告的汇编与映像自检数字为作者报告,未独立复现;复现入口见本页命令区,原统计版本待补。任务时间线属外部资料,已单独标记,不冒充源码证据。两处边界,如实标出。 ① 第 2 章「变量表不同 → 地址重排 → 机器码差异」这条因果链,是我从实测数字反推的机制解释;链上每一环都可复核,但没有 1960s 文档直接写下这个设计取舍。② 第 8 章的时间点来自 NASA 任务记录;源码能证实的只有「这些程序存在、各自做什么」,源码里没有时间戳。本页自包含 ,无外部依赖,无脚本,无 class,可直接粘进微信公众号与各类笔记软件。