本篇文章更新時間:2026/02/08
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知或向一介資男的 LINE 社群反應。
如果本站內容對你有幫助,歡迎贊助支持 。
內容目錄
SectorC:把 C Compiler 塞進 512 bytes 的極限挑戰
一個關於壓縮程式語言、重新發明 C、以及純粹工程浪漫的故事
編輯前言:這篇來自 xorvoid.com 的文章,講述作者如何在 512 bytes(沒錯,就是一個 boot sector)裡實現一個能編譯可用 C 程式的編譯器。讀完真的會讓人重新思考「程式到底需要多大?」
核心觀點 (Key Takeaways)
- 真正的瓶頸不是 CPU 或記憶體,而是我們對「必須要這麼做」的想像限制。
- 作者發明的 Barely C 語言,用「mega-token」與
atoi()hash 大幅縮減 tokenizer 成本,是突破點中的突破點。 - 透過極端的程式碼壓縮技巧(fall-through、call-fusion、byte alignment),一個「能寫出動態正弦波動畫」的 C 子集竟然能塞進 512 bytes。
深入解析
SectorC 是一個 x86-16 boot sector 裡的極限 C 編譯器,不但能解析相當完整的 C 語法(if、while、函式、運算子等),還能跑出如 VGA 正弦波動畫這種經典 demo 程式。作者一開始覺得不可能,但也因此激發了整篇文章最精華的兩個 insight。
Big Insight #1:把 C 切成「巨型 token」後,tokenizer 就變得超便宜。
傳統 C 的 tokenizer 難以壓縮——光 lexing 就超過 150 行 C code,若換成 x86-16 機械碼更是爆炸。但如果硬是把 C 重新「排版」成空白分隔的巨大詞彙?例如:
int(main)(){while(!done){
這整段變一個 token。語意雖怪異,但仍是合法 C。也因此,作者創造了所謂的 Barely C 語言,一個人類會崩潰但電腦超愛的 C 子集。
Big Insight #2:atoi() 其實是一個 hash 函式,用來分類 token 適合到不行。
atoi() 將字串轉成數字的過程,本質上就是字符流累積進 16-bit 值的雜湊。作者乾脆把所有 token 都丟進 atoi(),把識別字映射到 64K 的變數表、把運算子映射到對應指令、把數字維持數字本身。於是,不需要複雜的 tokenizer,也不需要 symbol table。
一層層極限壓縮:從 468 bytes → 303 bytes → 再塞進更多 C 功能
作者先用最直覺方式完成 Barely C,約 468 bytes。之後開始進行藝術級的壓縮,例如:
- 重組程式碼讓控制流「自然落下」而非使用 jmp
- 大量使用 tail-call
- 合併常用的 call (call-fusion)
- 優先用
cmp ax,imm省 bytes - 控制跳躍距離讓編碼維持 8-bit
最後把核心編譯器縮到 303 bytes,剩餘 207 bytes 用來加入更多語法支援,最終居然達到:
- 完整 if / while 區塊
- 運算子多達 14 種
- 函式定義與遞迴
- inline asm
- 單行與多行註解
- 甚至能讓程式碼「看起來像真的 C」
最讓我印象深刻的是作者用「binaryopertbl」來實現運算子——每個運算子只需 4 bytes(token + 機械碼),這才讓 C 真正變得「便宜」。
筆者心得與啟發
讀完 SectorC,我最大的感觸是:我們以為理所當然的抽象層、工具鏈、編譯流程,原來都可以被壓縮到荒謬的小。
這篇文章讓我重新思考三件事:
- 程式語言其實不需要複雜到那種程度。 C compiler 其實可以小到塞進一個 boot sector,我們每天用的工具未必真的需要那麼多層包裝。
- 限制反而帶來創造力。 512 bytes 的硬性邊界逼出「mega-token C」與「atoi-hash parsing」這種在一般情況根本不會有人認真考慮的點子。
- 工程不是只有生產工具,也可以是創作。 這專案彷彿是一件藝術品,展示了「在看似不可能的條件下,能被逼出什麼樣的巧思」。
若你對系統底層、編譯器、或極限程式設計有興趣,這篇文章不只是技術文章,更像一場腦洞大開的思考之旅。它提醒我:有時候學習不是為了解決問題,而是為了看見另一種可能性。
