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