WriteUp: 16 Bytes of x86 that turn Matrix rain into sound
194 points • 1 day agoArticle Link

于 2026 年 5 月在 Ommen, Netherlands 举行的 Outline Demoparty 上发布的 "wake up! 16b" 是一件引人注目的 demoscene 作品:它在仅用 16 字节 x86 实模式 DOS 汇编代码的条件下,探索了算法密度的极限。运行时,程序把显存既当作计算空间又当作显示缓冲区,用以渲染无限的谢尔宾斯基三角形,同时将这些几何数据解释为发送到 PC 扬声器的音频。整段程序仅由八条指令组成,总共 16 字节,可谓极简编码的极致实践。

代码以 int 10h 开始,初始化视频模式 0(40×25 字符文本模式)。随后两条指令将数据段寄存器指向 0xB800(VGA/CGA 文本缓冲区的物理地址)。在该中断清屏时,BIOS 会用统一模式填满所有 2000 个字符槽:ASCII 0x20(空格)和颜色属性 0x07(黑底浅灰)。表面上看似空白,实际上是一块填充了可预测、均匀数据的画布。这种均匀性至关重要,因为数学递推依赖一致的初始状态;内存中的任意随机伪影都会破坏分形,就像意外的一位能损坏元胞自动机那样。

程序的核心通过一个循环实现累加前缀和式的变换。 lodsb 从内存加载一个字节到累加器 AL,随后 sub si, byte 57 将源索引向后调整 56 字节(补偿 lodsb 的隐式自增)。接着 xor [si], al 把累加器与该位置的内存做异或,并把结果写回内存,从而在内存中形成一种"运行前缀和"的累积效果。在用 add 代替 xor 、步长为 16 字节且起始值为 2 的简化模型里,数值会按二项式系数序列累积;文章用表格演示了 16 个内存单元在 16 次遍历中逐行累加的过程,说明了这一数学递推。

关键在于用异或替代加法。二进制加法会产生进位并影响相邻位平面,而异或丢弃算术进位,等价于模 2 加法。起始值为 2(二进制 00000010),因此只有第 1 位会被影响。这把位平面隔离开来,使得值在 0x00 与 0x02 之间纯粹切换,恰好对应 Stephen Wolfram 的初等元胞自动机中的 Rule 60 。文章用第二个表格验证了这一点:第 1 位的置位与清零模式形成了典型的谢尔宾斯基三角形结构。

音频生成是该设计中最优雅的部分之一。 out 61h, al 将计算出的字节直接送到端口 61h,该端口连接内部 PC 扬声器。端口的第 1 位直接控制扬声器振膜:为 1 时向外推动,为 0 时回位。因为算法专门隔离并翻转第 1 位,谢尔宾斯基三角形的几何结构就直接变成了驱动扬声器振膜的指令。 CPU 的执行速度决定了有效采样率,1 与 0 的序列产生不同脉宽和频率的方波。交替的行会生成更高频的方波,而三角形内部的大块 0 区域则制造出节奏性的停顿,从而把数学结构直接转化为可听的声音纹理。

向后步进 56 字节(通过 sub si, byte 57)而不是向前步进 16 字节,对视听输出影响显著。 16 字节步长会在 4096 次迭代内完成一段扫掠,而 56 并不能整除 65536,需要 8192 次迭代才能访问所有地址,并在回到零之前绕段循环 7 次。这使宏周期加倍、基频减半,听起来下降一个八度,产生更慢更沉的音色。程序把结果写入 ASCII 字符字节:第 1 位用于控制扬声器,其余 7 位则演化出伪随机的 ASCII 字形,作为视觉纹理。值得注意的是,把这些混合数据发送到端口 61h 并不会导致系统崩溃,因为在标准 DOS 环境和常见模拟器中,多余的位会被无害地忽略。

在 40 字符宽显示上,-56 字节步进会产生对角剪切效果。向后 56 字节等同于在 80 字节行宽上向前 24 字节,即恰好 12 列;每个字符占 2 字节,因此序列每步上升 1 行并向右移动 12 列。由于 gcd(12,40)=4,循环恰好访问四分之一的列(40 列中的 10 列),于是分形以 10 列等间距的竖列形式在屏幕上向上展开,而非呈现为连续图像。

文章最后指出了对内存初始状态的依赖。理论模型假设环境被完美初始化,但实际中不同的系统配置、 VGA BIOS 实现和模拟器会在 RAM 中留下各种伪影。由于算法不断地读取并与现有内存内容做异或,它会直接与这些位交互,因而输出对运行环境高度敏感:视觉字符与音色在不同机器或模拟器上可能明显不同。虽然加入初始化例程以显式清除内存可以保证输出一致,但那会超出严格的 16 字节限制。接受这种微妙的不确定性,恰是在人为极限条件下创作的魅力所在。

32 comments • Comments Link

"Freespin"被重点介绍为一件引人注目的演示作品:它完全在软盘驱动器上运行,无需计算机,堪称极简计算的极致示例。

"Spongy"是一段 128 字节的作品,带来一次穿越门格海绵分形的"水下"旅程;人们更多地称赞它那种诡异的美感,而非纯粹的技术复杂性,说明美学冲击力可以胜过单纯的技术炫技。另有一个仅 64 字节的演示实现了"飞越一个 3D 灰度正交结构"的视觉效果,证明类似的视觉效果可以用比"Spongy"更小的代码体积完成。

"wakeup"被描述为令人震惊且几乎不可思议,一位评论者甚至称其看起来像"巫术",因为它在极端压缩下仍能实现视听上的高度一致。尤其令人意外的是,"wakeup"产生连贯的音乐而非噪音——考虑到它的极小体积以及对原始硬件输出的依赖,这一点尤其出人意料。该演示的开发过程优先考虑声音,视觉效果是由音频派生出来的,因此把它称为"将谢尔宾斯基声音转化为矩阵雨的 16 字节"同样贴切。

有人推荐"Rainy 32b"作为更轻松的替代品,展示了在极小体积演示中也能营造多样化氛围。"wakeup"的作者提到曾有一个音质更好的 COVOX 版本,但稳定性较差,最终提交的是一个稍逊但更可靠的版本参赛。比赛名次并不总能反映作品说明的质量——"wakeup"在比赛中排名第 6,但其作品说明排名第 2,这引发了关于大小编码比赛评判标准的讨论。

关于"wakeup"的技术细节:其通过视频内存和异或运算(沃尔夫勒姆规则 60)计算谢尔宾斯基分形,并通过端口 61h 直接驱动 PC 扬声器输出。代码中的 -56 字节步骤既制造了视觉上的对角剪切效果,又通过循环完成 64KB 内存段所需的 8,192 步来决定音频频率。硬件依赖性使得演示在不同机器和模拟器上表现各异——不同系统的内存初始化特性创造出独特的视听指纹,从而增强了每次运行的独特性。

作者在创作过程中进行了数百次多态汇编指令和元胞自动机的手动实验,"wakeup"之所以脱颖而出,部分原因是在调试过程中意外出现了动听的声音。社区对开发过程的幕后细节很感兴趣,因为讨论中分享的许多见解并未出现在官方作品说明里,这表明参与者非常重视那些隐藏的创作细节。

Demoscene 的讨论体现出对极致大小编码约束的深刻欣赏:通过巧妙利用硬件特性和数学属性,16 字节的作品也能生成连贯的视听体验。社区既重视技术成就,也重视美学感受,许多参与者更看重演示带来的情感冲击而非单纯的技术指标。开发过程既有系统性实验,也充满偶发发现,许多创作者在找到特别效果之前手动测试了数百种变体;硬件依赖性和初始化状态在这些微小演示中起着关键作用,使每次执行都有可能成为独一无二的体验。