16 字节的艺术:在 x86 汇编中构建谢尔宾斯基分形
软件领域对极端极简主义的追求通常被视为一种奇闻,但在 demoscene 中,这是一门严谨的学科。HellMood 在 2026 年 5 月的 Outline Demoparty 上发布的 demo "Wake up! 16b" 代表了这一学科的巅峰:一个仅使用 16 字节 x86 实模式 DOS 汇编代码,即可生成同步音频和视觉效果的全功能程序。
这不仅仅是一个“hack”,而是算法密度的精妙应用,它利用硬件的固有状态和二项式序列的数学特性来创建谢尔宾斯基三角形分形。以下是对这 16 字节如何操纵 1980 年代时代的 PC 以产生复杂涌现行为的深入探讨。
代码
要理解其中的魔力,我们必须首先查看源码。整个程序由以下指令组成:
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. 准备画布
程序首先调用 int 10h,这是一个 BIOS 中断,用于将视频模式重置为 40x25 文本网格。至关重要的是,这不仅仅是清屏;它还会以特定的模式初始化视频内存(位于 0xb800)。每个字符槽位由两个字节组成:ASCII 字符(初始化为 0x20,即空格)和颜色属性(初始化为 0x07,即黑底浅灰)。
通过依赖这种预先存在的状态而非显式地将内存清零,作者节省了宝贵的字节。程序随后将数据段 (ds) 指向 0xb800,有效地将 VGA/CGA 文本缓冲区转变为计算工作区。
2. 引擎:加法前缀和
其核心在于,该 demo 作为一个细胞自动机运行。要理解其数学原理,可以想象一个简化版本:内存被清零,且程序每次向前推进 16 字节。
随着程序的迭代,它在内存段中执行加法。由于 DOS 段的大小恰好是 65,536 字节,以固定增量移动可以确保指针能够干净地循环。这个过程会产生遵循二项式序列的部分和。当这些值被缩放并迭代时,它们会形成一种进位和溢出的模式,这种模式与 8 位寄存器的大小完美契合。
3. 通过 XOR 实现结晶化
虽然加法创建了二项式序列,但作者使用 xor 来隔离特定的位平面。在二进制逻辑中,XOR 本质上是无进位加法。
由于系统的初始状态(以及被操纵的特定值)针对的是第 1 位(二进制 00000010),程序实际上实现了初等细胞自动机的 Rule 60。根据卢卡斯定理(Lucas's theorem),这种特定的模二运算正是导致谢尔宾斯基三角形从二项式系数中涌现出来的原因。XOR 操作确保了只有该特定位的翻转被记录并播放。
4. 通感:从数据到音频
该 demo 最引人注目的特征之一是声音与视觉的同步。这是通过指令 out 61h, al 实现的。
端口 61h 是 PC speaker 的接口。发送到该端口的字节的第 1 位控制着扬声器振膜(1 为开启,0 为关闭)。通过将 XOR 计算的结果直接推入扬声器端口,分形的几何结构被转化为方波。
随着分形的演变,这些波形的脉冲宽度和频率会发生偏移,从而产生自相似的“bytebeats”。有趣的是,声音还会因为程序在整个 64KB 段上迭代(包括阴影 BIOS ROM 代码)而变得更加丰富,这为音频增添了一种在干净环境下不会出现的“颗粒感”纹理。
5. 空间扭曲:56 字节步进
为了创造视觉上的“Matrix rain”效果,作者避免了简单的线性推进。代码没有向前步进,而是结合使用 sub si, byte 57 和 lodsb(它会将 si 增加 1),从而导致每次迭代产生 -56 字节 的净移动量。
这一选择产生了两个深远的影响:
- 音频八度偏移: 56 不能被 65,536 整除。程序需要经过 8,192 步才能绕回段地址,这使得循环长度翻倍,并将声音的基础频率降低了一个八度。
- 视觉剪切: 在 80 列的屏幕上,向后移动 56 字节相当于向前移动 24 字节(12 列)。这导致分形呈现出对角线剪切效果,看起来像是十根字符柱状物向上移动,而不是一个静态的三角形。
硬件敏感性
由于程序是对 RAM 的现有内容进行 XOR 操作,输出结果对环境高度敏感。不同的 BIOS 版本或模拟器会在内存中留下不同的痕迹,这意味着 demo 的声音和外观会根据运行所在的机器而略有不同。
正如社区成员和 scener miragept 所指出的,在真实硬件上运行这段代码——例如使用 MDA 监视器的 IBM 286——由于旧显示器的磷光持久性,实际上可以让谢尔宾斯基结构更加清晰可见。这种对硬件自然状态的拥抱,正是 sizecoding 的标志性特征,在这里,环境并非 bug,而是一种特性。
"Embracing the hardware's natural state is just part of the charm of sizecoding."
这 16 字节的杰作展示了复杂性并不需要庞大的体积。通过理解数学、硬件架构和汇编语言的深层交集,几字节的代码就能唤起分形的涌现美感。