Hotdry.

Article

从16字节到256字节:Size-Coding极限优化的工程艺术

探索Demoscene Size-Coding的极限优化技术:VGA模式13h、Rrrola Trick、寄存器复用与代码压缩的工程实践。

2026-05-24systems

在软件体积不断膨胀的今天,Demoscene 社区却在进行一场逆向工程 —— 用越来越少的字节创造越来越震撼的视听效果。从 64KB 到 4KB,再到 256 字节、64 字节,直至 16 字节的极限前沿,Size-Coding 不仅是一种编程技巧,更是一门关于取舍、压缩与算法美学的工程艺术。

极限的起点:16 字节能做什么

在 MS-DOS 的.COM 格式中,一个程序可以从第一个字节就开始执行,没有头部开销,没有强制初始化。这种 "零开销" 特性使 DOS 成为 Size-Coding 的理想平台。然而,即便是这样一个极简环境,16 字节的上限仍然令人窒息。

以经典的 VGA 模式 13h(320×200 分辨率,256 色)为例,仅初始化图形模式和设置显存段寄存器就需要 8 个字节:

MOV AL, 13H     ; 设置图形模式
INT 10H         ; 调用BIOS
PUSH 0A000H     ; 显存段地址
POP ES          ; 存入ES寄存器

剩下的 8 字节中,无限循环(JMP)和像素写入(STOSB)又占去 3 字节,仅剩 5 字节用于实现实际效果。在如此严苛的限制下,"TV Noise" 这类简单效果已是极限。

然而,Viznut 的实验表明,16 字节并非只能产生无意义的噪点。通过巧妙地利用系统定时器($A1/$A2)的递增特性,结合 XOR、OR 等位运算,可以在音频和视频寄存器上创造出具有节奏感和宏观结构的 "类演示" 效果。这种 "混沌中的秩序" 正是 Size-Coding 的魅力所在。

256 字节的宏大舞台:Memories 案例分析

当字节预算扩展到 256 字节时,可能性空间呈指数级增长。HellMood 在 2020 年 Revision 大赛上的获奖作品 "Memories" 展示了这一预算下的工程极限 —— 一个包含 8 个视觉效果、MIDI 音乐、平滑过渡的 "微型演示"。

核心优化技术

Rrrola Trick:坐标变换的魔法

在 VGA 模式 13h 中,屏幕像素以行优先方式存储。传统方法用除法和取模计算 X、Y 坐标,但在 Size-Coding 中这是奢侈的。Rrrola Trick 使用魔数 0xCCCD 与屏幕指针 DI 相乘,通过高位和低位寄存器直接获得 X、Y 坐标:

MOV AX, 0CCCDH
MUL DI          ; DX = Y, AX = X * 0.8
ADD AL, AH
XOR AH, AH      ; AL = 伪随机值

这个技巧不仅避免了昂贵的 DIV 指令,还顺便产生了可用于效果的伪随机值。

寄存器复用:每一比特都珍贵

在 x86 实模式下,AX、BX、CX、DX 等寄存器是稀缺资源。Memories 框架中,DX 寄存器同时承载 X(DL)和 Y(DH)坐标;BP 寄存器既是时间计数器,又被 MIDI 音乐生成复用。这种 "寄存器重叠使用" 策略要求对指令副作用有精确把控。

代码与数据的双重压缩

Memories 中的 MIDI 音乐生成展示了极致的代码复用:

SOUNDS: DB 0C3H, 11, 93H

这里的 0C3H 既是 MIDI 的 "选择乐器" 指令,又恰好是 x86 的 RET 指令。通过精心安排代码布局,单个字节承担双重语义,节省了宝贵的字节预算。

效果实现的工程参数

Memories 中的 8 个效果展示了不同视觉算法的参数化实现:

Sierpinski Rotozoomer

传统旋转缩放需要三角函数计算,但 Memories 使用了一个数学技巧:利用 tan (atan (T)) = T 的特性,将缩放因子与旋转角度绑定,完全避免了三角函数调用。

Raycast Bent Tunnel

通过将距离值(CL)与投影坐标相乘,实现了伪 3D 隧道效果。关键参数包括:

  • 起始深度:-9(向后移动)
  • 弯曲偏移:+CL(向右弯曲)
  • 纹理模式:MOD 6 产生不规则图案

Ocean Night-to-Day

利用 FPU 的整数加载 / 浮点存储特性,通过将 XY 坐标解释为浮点数进行反向除法,生成波浪效果。天空到日出的颜色渐变则是 "框架副作用"—— 通过代码布局使 AL 寄存器恰好指向合适的调色板位置。

可落地的优化清单

对于希望实践 Size-Coding 的开发者,以下参数和技巧可直接应用:

初始化参数

  • 模式设置:AL = 0x13(320×200×256)
  • 显存段:ES = 0xA000
  • 定时器端口:40H(通道 0)
  • MIDI 端口:330H

核心常数

  • Rrrola 魔数:0xCCCD(坐标变换)
  • 投影常数:0x1329(倾斜平面效果)
  • 迭代魔数:819(视差棋盘效果)

渲染优化

  • 三重隔行扫描:通过 INC DI 两次实现,平滑动画
  • 目标帧率:35 FPS(tempo = 1193182/256/35)
  • 伪随机生成:屏幕指针 DI 的变换残差

寄存器分配策略

  • DI:屏幕指针(硬件自动递增)
  • BP:时间 / 帧计数器
  • DX:X/Y 坐标(DL/DH 分割)
  • AL:像素颜色值(STOSB 要求)

从极限到工程实践

Size-Coding 的技术不仅适用于演示程序。在嵌入式系统、引导加载程序、网络协议栈等场景中,类似的优化思维同样适用:

  1. 算法替代存储:用运行时计算替代查找表,在 RAM 受限设备中尤为重要
  2. 副作用编程:利用指令的隐式行为(如标志位、寄存器高位)传递信息
  3. 布局优化:通过代码重排使数据天然对齐,减少初始化开销
  4. 硬件直通:绕过抽象层直接操作寄存器,降低延迟和代码体积

Size-Coding 的哲学提醒我们:软件的本质复杂度往往远低于其实现复杂度。在 111MB 甚至更大的限制下,我们或许已经忘记了如何精打细算;但 16 字节的前沿探索,让我们重新认识到每一比特的价值。


参考来源

  • SizeCoding.org Wiki - "Memories" 详细技术解析
  • Viznut - "The 16-byte frontier: extreme results from extremely small programs"
  • Pouet.net - Demoscene 作品档案库

systems

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com