ESI 深度实战:当软件想要活过1000年——从 Subleq+ 极简虚拟机到 LLVM 后端、Linux 胶囊与长期保存的完全指南(2026)
2026 年 6 月,一个名为 Eternal Software Initiative(ESI) 的开源项目把“软件永生”这个听起来像科幻的命题,变成了一套可下载、可编译、可运行的技术栈。它的野心很大:用一段足够短的描述,让一千年后的人重建一台计算机,并直接运行今天的软件。更疯狂的是,这台计算机的指令集只有 一条指令:
subleq。本文将从 WHY、WHAT、HOW 三个层面,把 ESI 的设计哲学、极简架构、LLVM 后端、Linux 胶囊、以及一个可运行的 Subleq+ 虚拟机完整拆开,看看它到底是在做赛博诺亚方舟,还是一次值得每个程序员思考的工程实验。
一、软件为什么会“死”?——从 10 年半衰期说起
我们每天都在写代码,却很少认真想过:代码本身能活多久? 一个 Java 程序依赖特定版本的 JDK、Spring Boot、MySQL 驱动、某个 Kubernetes 发行版;一个前端项目被 npm 依赖树裹成粽子;一个游戏依赖 closed-source 的物理引擎和 DRM 服务器。只要其中任何一个环节停止维护,整件“数字文物”就会在几年到十几年内腐烂。
ESI 官网给了一个很扎心的对比:
| 介质 | 寿命 |
|---|---|
| 泥板 | 5000+ 年,今天仍可读 |
| 软件 | ~10 年,依赖就开始过时 |
这不是危言耸听。今天的考古学家可以读懂几千年前的楔形文字,但 100 年后的工程师未必能跑起来一个 2026 年的 Docker 镜像。因为软件不是单一物品,它是一个生态系统:硬件、操作系统、编译器、运行时、库、框架、协议、证书、在线服务,全部要在位且兼容。一旦某一层缺失,整个金字塔就塌了。
传统的应对方案是模拟器。QEMU、DosBox、MAME 等工具把旧硬件翻译成软件,让老程序在现代 CPU 上运行。但模拟器本身也是数百万行代码,依赖现代语言、库和操作系统。你能想象 1000 年后的人先读懂 QEMU 源码、再复现 x86 的乱序执行、UEFI 启动流程、PCIe 枚举,然后才能运行你写的一个 Python 脚本吗?
“你不能用更复杂的东西去保存复杂的东西,你必须简化。” 这是 ESI 的出发点。它选择了一个极简到不可思议的靶子:一台只有一条指令的计算机。只要未来的人能理解这条指令,就能重建整台机器,进而恢复一整套现代软件。
二、Subleq+:一条指令的图灵机
Subleq 是“SUbtract and Branch if Less than or EQual to zero”的缩写。它只有一条指令:
subleq A, B, C
语义极其简单:
M[B] = M[B] - M[A]- 如果结果
<= 0,跳转到地址C - 否则继续执行下一条指令
其中 A、B、C 都是内存地址。整个计算机的状态就是一片可读写的内存加一个程序计数器(PC)。没有寄存器,没有特殊寄存器,没有复杂的寻址模式。你甚至可以把 CPU 规范写在一张餐巾纸上。
2.1 图灵完备:一条指令够吗?
很多人第一反应是:“这能干什么?”答案是:Subleq 是图灵完备的。也就是说,它能表达任何可计算问题。证明思路很直接:
- 条件跳转:
subleq Z, Z, label先把Z清零,再subleq A, Z, label,若A <= 0则跳转。因为M[Z] = 0 - M[A],当M[A] <= 0时结果>= 0?等等,需要更仔细地构造。但经典结论是:通过适当选择A、B、C,可以实现分支、循环、函数调用。 - 算术运算:加法
C = A + B可以通过A = A - (-B)实现;乘法可以通过循环累加实现;位运算可以通过算术技巧实现。 - 内存访问:直接寻址已经够表达任何数据移动。
所以 Subleq 不仅“能跑”,而且在理论上可以跑任何程序。问题是,纯 Subleq 写程序太啰嗦。于是 ESI 做了一个关键扩展:Subleq+。
2.2 Subleq+ 的升级:间接寻址
Subleq+ 在 Subleq 的基础上加入了间接寻址。官方说法是:这提供了“指针支持”,使得可重入代码、栈、函数调用成为可能,也让运行现代操作系统不再是天方夜谭。
在我们的示例实现里,可以把一条指令扩展为 4 个内存字:
[OP, A, B, C]
其中 OP 的高几位表示寻址模式:
| OP 标志 | 含义 |
|---|---|
| 0 | 直接:A 和 B 都是地址 |
| 1 | A 间接:M[A] 作为源地址 |
| 2 | B 间接:M[B] 作为目标地址 |
| 3 | A 和 B 都间接 |
执行语义:
src = (op & 1) ? M[M[A]] : M[A]
dst = (op & 2) ? M[M[B]] : M[B]
M[dst_addr] -= src
if M[dst_addr] <= 0:
PC = C
else:
PC += 4
注意:这里的“目标地址”和“目标值”要分开。如果是直接模式,目标地址就是 B,目标值就是 M[B];如果是间接模式,目标地址是 M[B],目标值是 M[M[B]]。这个细节是 Subleq+ 能支撑高级语言的关键:它让我们可以用一个指针指向内存,再对那块内存做读写。
2.3 一段 Subleq+ 汇编示例:两数相加
; 计算 M[sum] = M[a] + M[b]
Z: .word 0
a: .word 7
b: .word 5
sum: .word 0
start:
subleq Z, Z, next ; Z = 0
next:
subleq b, Z, next2 ; Z = 0 - b = -b
next2:
subleq Z, sum, end ; sum = sum - (-b) = sum + b
end:
halt
这段代码只有 3 条有效指令,却展示了 Subleq+ 编程最核心的技巧:用临时变量把加法变成减法。因为指令只有减法,所以加法 x + y 要写成 x - (-y)。先把 y 取负存入临时变量,再用一次减法把它加回去。这是所有高级语言被编译到 Subleq+ 时的底层模式之一。
三、Eternal Computer 架构全景
Eternal Computer 不是一台真实物理机,而是一个目标架构规范加一个参考虚拟机。它的设计目标不是跑得最快,而是“最容易被未来的人重建”。因此它的架构有以下几个特征:
3.1 扁平内存模型
所有数据都放在一个统一的大数组里。没有寄存器文件、没有缓存一致性协议、没有特权级。一个字有多大?ESI 的实现选择了 32 位或 64 位有符号整数。在本文的示例里,我们统一使用 32 位有符号整数。
这意味着:
- 指针就是一个整数地址。
- 栈指针也是内存里的一个普通字。
- 进程切换时,只需要保存 PC 和若干内存字,不需要保存寄存器上下文。
3.2 指令格式
一条 Subleq+ 指令占 4 个字:
[OP | A | B | C]
程序计数器每次默认前进 4。如果 OP == -1,表示停机。整个指令集规范不到 200 个字符就能写清楚。
3.3 内存映射 I/O
为了和外部世界交互,ESI 的 VM 通常把一部分地址空间留给 I/O。例如:
- 某个固定地址写字符,即向控制台输出。
- 某个固定地址读字符,即从键盘输入。
- 图形版本会有一块帧缓冲区,也是内存的一部分。
这样一来,运行《毁灭战士》只需要把显存映射到帧缓冲区,然后由 VM 把这块内存渲染到屏幕。没有驱动程序,没有复杂的 GPU 接口,只有“读内存→显示像素”。
3.4 架构与实现的解耦
规范是规范,实现是实现。参考 VM 可以用 50 行 C 写完;你也可以用 Python 写一个教学版;未来的人甚至可以用齿轮、继电器或 DNA 链实现。只要它执行同一条指令集,同一个 capsule 就能跑起来。这种规范与实现的解耦是长期保存的核心:复杂的是硬件实现,保存的却只有一串数字和一页规范。
四、把 C/C++ 和 Linux 塞进 Subleq+:LLVM 后端与系统移植
如果你只是做了一个一指令 CPU,没人会理你。ESI 真正让人震惊的是:他们给这个 CPU 做了一个 LLVM 后端,把 C/C++ 程序编译成 Subleq+ 指令流,还移植了 Linux、uClibc-ng 和 BusyBox。
4.1 LLVM 后端:从高级语言到极简指令
LLVM 的架构是模块化的。你可以为新的 CPU 定义一个 Target:描述寄存器、指令集、调用约定、ABI、汇编格式。然后 LLVM 的代码生成器会完成指令选择、寄存器分配、指令调度。
但 Subleq+ 几乎没有寄存器,所以它的后端更像是一个栈机/内存机后端:
- 前端把 C 代码编译成 LLVM IR。
- 后端把 LLVM IR 里的每个操作(
add、load、store、call、ret)翻译成 Subleq+ 指令序列。 - 由于没有寄存器,所有中间结果都存放在内存的临时槽位里。
- 函数调用约定:参数按顺序压入栈,返回地址也放在内存里,栈指针由 Subleq+ 间接寻址维护。
来看一个最简的 C 函数如何被“脑内编译”到 Subleq+:
int add(int a, int b) {
return a + b;
}
在 Subleq+ 后端里,它可能被翻译成类似下面的伪代码(假设栈从高地址向低地址增长,参数已经通过调用者压栈):
; 帧布局简化示意
; sp 指向栈顶
; 参数 a 在 sp+1,参数 b 在 sp+2
; 返回值写回 sp+1
subleq tmp, tmp, next ; tmp = 0
next:
subleq [sp+2], tmp, next2 ; tmp = -b
next2:
subleq tmp, [sp+1], ret ; a = a + b,结果留在原 a 的位置
ret:
; 恢复栈,跳转到返回地址
真实的 LLVM 后端当然要处理类型、对齐、调用约定、优化、调试信息,但底层模式就是:不断用临时零槽和 subleq 的组合,把所有高级抽象还原成内存之间的减法。
4.2 为什么选 uClibc-ng 和 BusyBox?
ESI 的目标不是重造一个 Linux 发行版,而是构造一个能自举的最小 Linux 环境。所以选择:
- uClibc-ng:一个为嵌入式系统设计的 C 库,体积比 glibc 小得多,功能却足够运行大多数 Linux 程序。因为它是 C 写的,可以被 ESI 的 LLVM 后端直接编译。
- BusyBox:把 dozens of Unix 工具合并成一个可执行文件,俗称“嵌入式 Linux 瑞士军刀”。它让胶囊里的根文件系统保持最小。
- Linux 内核:ESI 需要把内核里与架构相关的部分(启动、上下文切换、中断/异常、系统调用、页表或内存保护)重新实现到 Subleq+ 上。因为 Subleq+ 支持间接寻址,所以可以维护进程栈、保存 PC、实现抢占式多任务。
最后,内核、C 库、Shell、应用程序全部编译成 Subleq+ 指令,被打包进一个胶囊。
五、Capsule:把软件封进一串数字
ESI 对“软件永生”给出的工程答案是 Capsule(胶囊)。它的定义非常朴素:
A capsule is a sequence of numbers that encodes an entire software stack — OS, libraries, applications — into a single self-contained artifact.
也就是说,最终交付物不是 ISO 镜像、不是 Docker 镜像、不是 git 仓库,而是一串整数。这串整数可以刻进钛合金圆柱、写进玻璃、打印在纸上,甚至编成一首歌。只要未来有人按规范重建 Eternal Computer VM,把数字加载进内存,软件就会重新运行。
5.1 胶囊的结构
一个最小化的胶囊可以想象成:
[ 魔数 | 内核长度 | 根文件系统长度 | 应用数据长度 | 内核字节... | 根文件系统字节... | 应用数据字节... ]
因为 Subleq+ 的字长是整数,所以所有字节数据会被对齐成 32 位或 64 位字。VM 启动时:
- 读取魔数,确认格式版本。
- 把内核加载到固定起始地址。
- 把根文件系统加载到另一段地址。
- 设置 PC 到内核入口点。
- 开始执行。
5.2 一个玩具级胶囊打包器
下面是一个用 Python 写的概念级打包器,展示如何把多个二进制片段合并成一个胶囊文件:
import struct
MAGIC = 0xE51CA_0001 # 假的魔数,仅用于演示
def pack_capsule(parts):
"""
parts: [(name: str, data: bytes), ...]
返回:扁平化的整数列表,每个整数占 32 位。
"""
# 头部:魔数 + 段数
header = [MAGIC, len(parts)]
# 每个段的目录项:名字长度、数据偏移(字)、数据长度(字)
directory_size = len(parts) * 3
data_offset = 2 + directory_size
directory = []
payloads = []
cur = data_offset
for name, data in parts:
name_bytes = name.encode('utf-8')
name_len = (len(name_bytes) + 3) // 4
data_len = (len(data) + 3) // 4
directory += [name_len, cur, data_len]
padded_name = name_bytes + b'\0' * (name_len * 4 - len(name_bytes))
padded_data = data + b'\0' * (data_len * 4 - len(data))
payloads += list(struct.unpack('<' + 'I' * name_len, padded_name))
payloads += list(struct.unpack('<' + 'I' * data_len, padded_data))
cur += name_len + data_len
return header + directory + payloads
# 示例:把两个“二进制文件”打包成胶囊
parts = [
("kernel", b'\x00\x01\x02\x03'), # 假的内核
("initrd", b'hello capsule'), # 假的根文件系统
]
capsule = pack_capsule(parts)
with open('demo.capsule', 'wb') as f:
for word in capsule:
f.write(struct.pack('<I', word & 0xffffffff))
print(f"生成胶囊,共 {len(capsule)} 个字,{len(capsule)*4} 字节")
这个示例当然不能运行真实的 Linux,但它揭示了胶囊的本质:用一段可自我描述的整数序列,把多个软件组件绑定成单一工件。真实的 ESI 工具链会更复杂(例如 ELF 重定位、动态链接、符号表、压缩、校验和),但核心思想不变。
5.3 为什么“一串数字”比“Docker 镜像”更适合保存?
Docker 镜像本质上是 Linux 文件系统的层级快照,它的可运行性依赖于:x86 CPU、Linux 内核、containerd、runc、OCI 规范、网络、DNS、仓库认证。只要这些外部依赖中有一个在未来失效,镜像就不可解释。
而胶囊的依赖是:知道 Subleq+ 指令语义、能存储数字、能减法。这门槛低得多。你甚至可以把 VM 规范和 capsule 一起刻在石碑上:
subleq a,b,c: mem[b] -= mem[a]; if mem[b] <= 0 goto c。
下面是 1,247,893 个数字。加载它们,从地址 0 开始执行。
六、动手实现一个 Subleq+ 虚拟机
理论说再多,不如跑一段代码。下面我们用 Python 实现一个教学版 Subleq+ VM,再配一段汇编代码,展示它真的能算出结果。
6.1 Python 版 Subleq+ VM
import sys
MMIO_OUT = -1 # 写入该地址即输出字符
MMIO_IN = -2 # 读取该地址即输入字符
def run(image, pc=0):
"""
image: 初始内存,整数列表
pc: 起始程序计数器
"""
M = image[:] + [0] * (1 << 18) # 预留 1M 字空间
stdin = iter(sys.stdin.read())
while True:
op = M[pc]
if op == -1:
break
a = M[pc + 1]
b = M[pc + 2]
c = M[pc + 3]
pc += 4
# 取源地址和源值
if op & 1:
src_addr = M[a]
else:
src_addr = a
src = M[src_addr] if src_addr != MMIO_IN else ord(next(stdin, '\0'))
# 取目标地址
if op & 2:
dst_addr = M[b]
else:
dst_addr = b
# 执行减法并写回
if dst_addr == MMIO_OUT:
sys.stdout.write(chr(src & 0xff))
else:
M[dst_addr] -= src
res = M[dst_addr]
if res <= 0:
pc = c
if __name__ == '__main__':
# 从文件读取整数列表,空格分隔
words = list(map(int, open(sys.argv[1]).read().split()))
run(words)
这个 VM 有这几个要点:
- 每条指令 4 个字:
OP, A, B, C。 OP的最低两位控制间接寻址:0:直接-直接1:间接 A2:间接 B3:间接-间接
OP == -1时停机。- 用
-1和-2做两个内存映射 I/O 地址,方便做“Hello World”。
6.2 计算 1 + 2 + ... + 10 的 Subleq+ 程序
下面是一段用文本助记符写的程序,配合一个极小的汇编器即可运行:
; 寄存器/变量定义
Z: .word 0
one: .word 1
n: .word 10
sum: .word 0
loop:
subleq Z, Z, l1 ; Z = 0
l1:
subleq n, Z, l2 ; Z = -n
l2:
subleq Z, sum, l3 ; sum += n
l3:
subleq one, n, done ; n -= 1; if n <= 0, done
subleq Z, Z, loop ; 无条件跳回 loop(Z 已经是 0)
done:
halt
这段代码最终把 1+2+...+10 = 55 写入 sum 所在的内存字。它没有用到间接寻址,但已经展示了 Subleq+ 里循环、条件分支、累加三大基本控制结构是怎么用减法拼出来的。
6.3 C 语言参考 VM:50 行真的够
ESI 官方说参考 VM 用 C 写大约 50 行。下面是一个等价但更紧凑的版本,突出“餐巾纸级复杂度”:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char **argv) {
int32_t M[1 << 20], pc = 0, n = 0;
FILE *f = fopen(argv[1], "rb");
while (fread(&M[n], sizeof(int32_t), 1, f)) n++;
fclose(f);
while (1) {
int32_t op = M[pc], a = M[pc+1], b = M[pc+2], c = M[pc+3];
if (op == -1) break;
pc += 4;
int32_t src = (op & 1) ? M[M[a]] : M[a];
int32_t *dst = (op & 2) ? &M[M[b]] : &M[b];
*dst -= src;
if (*dst <= 0) pc = c;
}
return 0;
}
编译命令:
gcc -O2 eternal_vm.c -o eternal_vm
./ eternal_vm demo.capsule
就这几行代码,已经足够表达一个能运行 Linux 的虚拟机。这是 ESI 最震撼人的地方:
不是“这台机器很强大”,而是“这台机器的简单性让它可以活很久”。
七、性能优化:让极简架构跑得快
Subleq+ 的简单是有代价的:执行同样算法,它可能需要比 x86 多几个数量级的指令。但 ESI 不是要替代现代 CPU,而是要提供一个可长期保存的通用规范。在这个前提下,性能可以通过规范层之上的优化来解决。
7.1 虚拟机实现层优化
即使是同一个规范,VM 实现也可以很快:
- 直接内存映射:不要每条指令都解码,而是把 capsule 直接映射到内存数组,PC 递增 4。
- 计算跳转(computed goto):用 GCC 的
&&label特性把指令分发从switch改成跳转表,减少分支预测失败。 - 超指令(superinstruction):把常见的指令序列(如
清零临时变量 + 取负 + 加法)合并成一条内部超指令,减少分发开销。 - 缓存友好的内存布局:尽量让热路径数据在相邻地址,利用 CPU 缓存。
7.2 提前编译与即时编译
更激进的做法是:把 capsule 里的 Subleq+ 指令翻译成宿主 CPU 的机器码。例如:
- AOT(Ahead-of-Time):启动时扫描整个 capsule,为每个 Subleq+ 基本块生成对应 x86 或 ARM 指令,然后直接执行原生代码。
- JIT(Just-in-Time):只在热点路径上动态编译,冷路径保留解释执行。
这样,用户在前端得到接近原生的速度,但底层保存格式仍然是那串数字。未来的人哪怕没有 AOT/JIT 技术,也能用最简单的解释器把软件恢复出来。性能优化不污染保存格式,这是分层架构的胜利。
7.3 硬件实现
如果你真愿意,可以直接在 FPGA 或 ASIC 上实现 Subleq+ 处理器。因为它只有一条指令,控制逻辑极小。你可以做出一个能耗极低、寿命极长的“千年计算机”原型。它不需要乱序执行、分支预测、缓存一致性,只需要:
- 一个减法器
- 一个比较器
- 一个程序计数器
- 一个内存接口
这对于太空探测器、地质档案馆、核废料存储设施等“需要长期自主运行”的场景特别有吸引力。
八、能跑 DOOM,还能保存什么?
ESI 的演示 capsule 里已经能跑 DOOM——这款游戏是程序员圈的“经典试金石”。如果一个系统能跑 DOOM,说明它至少有:
- 可工作的 CPU
- 可运行的操作系统(至少文件系统 + 进程调度)
- 图形输出能力
- 用户输入处理
- 足够的内存和性能
所以 DOOM 不仅是游戏,它是一个最小化的现代软件生态验证。ESI 能跑 DOOM,意味着它已经把“硬件抽象层、操作系统、C 库、图形、输入”这一整串链路跑通了。
8.1 适合保存的软件
Subleq+ + Linux 胶囊最适合保存的是:
- 开源操作系统和系统工具:Linux、BusyBox、uClibc-ng、coreutils、编辑器。
- 科学计算和模拟程序:依赖 CPU 计算、不依赖在线数据库或专有硬件的程序。
- 经典游戏:DOOM、Quake、大量独立游戏。
- 文档与数字艺术:如果把渲染器也打包进去,PDF、图片、文本都可以变成可运行对象。
- 开发工具链:编译器、解释器、构建系统,让未来的人可以在这个环境上继续开发。
8.2 不太容易保存的东西
也要诚实地说,ESI 不能包治百病:
- 强依赖云服务的应用:在线协作、流媒体、SaaS,一旦服务器消失,前端再完整也没用。
- 专有硬件驱动:GPU 加速、TPU、专用 DSP,这些程序依赖无法被标准化的黑盒硬件。
- 需要实时交互和极低延迟的系统:高频交易、工业控制,Subleq+ 的抽象层开销太大。
- 法律和授权问题:很多软件不是开源的,即使技术上能打包,法律上也不能随意保存和分发。
所以 ESI 更像是一个数字文明的“种子库”,而不是“把所有软件都冻起来”的万能方案。
九、总结:一次关于“时间”的程序员实验
Eternal Software Initiative 让我想到一个问题:我们每天写代码,到底是在建造,还是在制造短期消费品?
ESI 给出的答案不是“让我们回到 1980 年代”,而是**“用最简单的抽象层,把复杂度锁进当下,把未来交给未来”**。它用 Subleq+ 这条极简指令作为时间胶囊的通用语言,用 LLVM 后端把现代软件翻译进去,用 Linux 胶囊把完整生态封装起来,最终交付物只是一串数字。
这套方案的可贵之处不是性能,而是思想:
- 简化才能永生:复杂的东西必须依赖更多复杂的东西,而简单的东西只需要被理解。
- 规范与实现分离:保存规范,让未来的实现者自行选择最合适的硬件。
- 自包含:把所有依赖都放进一个胶囊,而不是依赖外部不断变化的生态。
- 分层优化:保存格式保持极简,运行时可以通过 VM、AOT、JIT、硬件任意加速。
作为一个程序员,我未必会把明天的生产环境直接搬到 ESI 上,但我会把它当作一个思考工具:每次引入一个新依赖、一个新框架、一个云原生服务时,问问自己——如果 50 年后有人要运行这段代码,他需要知道多少东西?
如果答案是“很多,而且大多数都依赖还在运营的公司”,那这段代码可能正在走向 ESI 所说的“10 年半衰期”。
1000 年的软件保存听起来宏大,但它背后的工程原则其实很小:
用最少的假设,做最长久的承诺。
十、给程序员的实践启发:如何写更长寿的代码
ESI 最牛的地方不是它的代码,而是它提出的问题:我们该用什么标准评价一段代码的“生命周期”?
在 2026 年的开发者眼里,一个好项目通常看:CI 绿不绿、测试覆盖率、QPS、启动速度、社区 Star 数。但很少有人问:如果 30 年后我的依赖仓库 404 了,这段代码还能不能编译?如果 100 年后没有 npm、没有 Docker Hub,它还能不能被理解?
ESI 给出了一组可以迁移到日常工程的启发:
降低外部依赖的“隐式深度”
每引入一个依赖,都要想一想它背后又依赖了什么。一个日志库可能拉起半打 JSON 解析器和网络客户端。对于要长期维护的核心模块,依赖越少,未来被恢复的概率越高。用文本协议和明文格式保存数据
二进制专有格式在未来几乎无法被逆向。CSV、JSON、Markdown、纯文本日志,虽然低效,但可读性极强。ESI 用“一串整数”保存软件,也是同一思想的极致。把架构假设写进文档,而不是藏在代码里
未来的维护者不会知道你为什么用某个特定的 API。把架构决策、约束、不可变假设写成 ADR(Architecture Decision Records),是降低未来理解成本最有效的做法。保留可自举的构建链
如果项目需要 17 个现代 SaaS 才能编译,那它的寿命不会超过这些 SaaS 的寿命。保留一个能离线运行的、最小化的构建脚本,是一种“数字末日保险”。接受性能与寿命的权衡
就像 ESI 用极简指令换取可解释性,有时候为了长期可维护,我们应该主动选择更“笨”但更少依赖的方案。一个手写的小脚本,可能比一个基于 20 个微服务的系统活得更久。
这些原则不是让我们退回到石器时代的开发方式,而是提醒:不要把“现在能跑”等同于“未来还在”。短期看,复杂的架构和依赖能提升效率;长期看,它们会加速腐烂。
参考与延伸阅读
- Eternal Software Initiative 官网:https://eternal-software.org/
- 相关报道:Eternal Computer 极简虚拟机发布(2026-06-18/19)
- Subleq 图灵完备性证明:OISC(One Instruction Set Computer)相关文献
- LLVM 后端开发文档:LLVM Target-Independent Code Generator
- uClibc-ng、BusyBox、Linux 内核源码
本文示例代码为教学简化版,不代表 ESI 官方实现的精确 ABI 或文件格式。实际使用请以官方仓库和文档为准。