16 位元組的藝術:在 x86 組語中工程化 Sierpinski 分形

軟體極致極簡主義的追求通常被視為一種奇聞,但在 demoscene 中,這是一門嚴謹的學科。HellMood 在 2026 年 5 月的 Outline Demoparty 上發布的 demo "Wake up! 16b",代表了這門學科的巔峰:一個僅使用 16 位元組的 x86 real-mode DOS 組語,就能生成同步音訊與視覺效果的完整功能程式。

這不僅僅是一個 "hack",而是演算法密度的精妙應用,利用硬體固有的狀態與二項式序列的數學特性來創造 Sierpinski 三角形分形。以下將深入探討這 16 位元組如何操縱 1980 年代的 PC,以產生複雜的湧現行為。

The Code

要理解這項魔術,我們必須首先查看原始碼。整個程式由以下指令組成:

int 10h          ; 2 bytes
mov bh, 0xb8     ; 2 bytes
mov ds, bx       ; 2 bytes
L:
lodsb            ; 1 byte
sub si, byte 57  ; 3 bytes
xor [si], al     ; 2 bytes
out 61h, al      ; 2 bytes
jmp short L      ; 2 bytes

1. Priming the Canvas

程式開始時會調用 int 10h,這是一個 BIOS 中斷,會將影片模式重置為 40x25 文字格。至關重要的是,這不僅僅是清除螢幕;它還會以特定模式初始化影片記憶體於 0xb800。每個字元插槽由兩個位元組組成:ASCII 字元(初始化為 0x20,即空格)與顏色屬性(初始化為 0x07,即黑底淺灰)。

透過依賴這種預先存在的狀態而非顯式地將記憶體清零,作者節省了寶貴的位元組。接著,程式會將資料段 (ds) 指向 0xb800,有效地將 VGA/CGA 文字緩衝區轉變為計算的工作空間。

2. The Engine: Additive Prefix Sums

其核心運作方式如同一個細胞自動機。要理解其數學原理,可以想像一個簡化版本:記憶體被清零,且程式每次向前推進 16 位元組。

隨著程式迭代,它會在記憶體段中執行加法。由於 DOS 段的大小正好是 65,536 位元組,以固定增量移動可以確保指標會乾淨地回繞。這個過程會產生遵循二項式序列的偏和(partial sums)。當這些值被縮放與迭代時,它們會形成一種與 8 位元暫存器大小完美對齊的進位與溢位模式。

3. Crystallization via XOR

雖然加法產生了二項式序列,但作者使用 xor 來隔離特定的位元平面(bitplanes)。在二進制邏輯中,XOR 本質上是無進位的加法。

由於系統的初始狀態(以及被操縱的特定值)針對的是第 1 位元(二進制 00000010),程式有效地實現了初等細胞自動機的 Rule 60。根據 Lucas 定理,這種特定的模二運算正是導致 Sierpinski 三角形從二項式係數中湧現的原因。XOR 運算確保了只有這個特定位元的切換(toggling)會被記錄並回放。

4. Synesthesia: From Data to Audio

該 demo 最引人注目的特性之一是聲音與視覺的同步。這是透過指令 out 61h, al 實現的。

連接埠 61h 是 PC speaker 的介面。傳送到此連接埠的位元組中,第 1 位元控制著揚聲器振膜(1 為輸出,0 為內收)。透過將 XOR 計算的結果直接推入揚聲器連接埠,分形的幾何結構被轉化為方波。

隨著分形的演化,這些波形的脈衝寬度與頻率會發生偏移,產生自相似的 "bytebeats"。有趣的是,聲音會因為程式迭代遍歷整個 64KB 段(包括陰影 BIOS ROM 程式碼)而進一步豐富化,為音訊增感到了一種在乾淨環境中不會出現的 "gritty"(粗糙)紋理。

5. Spatial Distortion: The 56-Byte Step

為了創造視覺上的 "Matrix rain"(矩陣雨)效果,作者避免了簡單的線性進展。程式碼並非向前推進,而是使用 sub si, byte 57 結合 lodsb(這會使 si 增加 1),導致每次迭代的淨移動量為 -56 位元組

這個選擇產生了兩個深遠的影響:

  • Audio Octave Shift: 56 並不能整除 65,536。程式需要 8,192 次步驟才能回繞整個段,這使週期長度翻倍,並將聲音的基頻降低了一個八度。
  • Visual Shearing: 在 80 欄位的螢幕上,向後移動 56 位元組相當於向前移動 24 位元組(12 欄位)。這會導致分形產生斜向剪切(shear),看起來像是十根字符的柱狀物向上移動,而非靜態的三角形。

Hardware Sensitivity

由於程式會對 RAM 的現有內容進行 XOR 運算,輸出結果對環境高度敏感。不同的 BIOS 版本或模擬器會在記憶體中留下不同的殘留物,這意味著 demo 的聲音與視覺效果會根據運行所在的機器而略有不同。

正如社群成員與 scener miragept 所指出的,在真實硬體上運行這段程式碼——例如使用 MDA 單色顯示器之 IBM 286——實際上可以讓 Sierpinski 結構更加清晰可見,因為舊顯示器的磷光持久性(phosphor persistence)會產生效果。這種對硬體自然狀態的擁抱,正是 sizecoding 的標誌性特徵,在這種模式下,環境並非錯誤(bug),而是特性(feature)。

"Embracing the hardware's natural state is just part of the charm of something like sizecoding."

這 16 位元組的傑作展示了複雜性並不需要龐大的體積。透過理解數學、硬體架構與組語的深度交集,僅僅幾位元組的程式碼就能喚起分形的湧現美感。

Sources