
2026 年 8 月 7 日,安全研究员 Christopher Domas(@xoreaxeaxeax)发布了新项目 Assembly Hall of Shame(汇编耻辱堂)。项目目标只有一个:让 CPU 慢到极限。
大多数性能研究都在想办法让代码跑得更快。Domas 反过来,系统性地寻找 x86 指令集中单条指令能慢到什么程度。结果是:最快的 nop 指令 1 个周期(0 纳秒),最慢的 fxrstor64 跑了 1980 亿个周期,耗时 62 秒。两者相差超过 11 个数量级。
排行榜:从 0 纳秒到 62 秒
项目维护了一份 x86 指令延迟排行榜,按周期数从快到慢排列。以下是关键节点:
| 排名 | 指令 | 策略 | 周期数 | 耗时 | 硬件 |
|---|---|---|---|---|---|
| 27 | nop | 什么都不做 | 1 | 0 ns | Intel i7-8559U |
| 24 | idiv | 128 位除法溢出触发最长微码路径 | 77 | 28 ns | Intel i7-8559U |
| 22 | fsin | 特殊值触发微码浮点处理 | 257 | 94 ns | Intel i7-8559U |
| 16 | split lock | 跨缓存行边界原子锁,强制外部总线锁 | 865 | 319 ns | Intel i7-8559U |
| 13 | rdrand | 循环耗尽硬件熵池 | 5,579 | 2.0 μs | Intel i7-8559U |
| 12 | wrmsr | 写 MCG_CTL,触发 Zen 微码全局同步 | 34,304 | 10.7 μs | AMD Ryzen 7 5800H |
| 9 | wbinvd | 填满脏缓存行后全量回写 | 1,616,480 | 506 μs | AMD Ryzen 7 5800H |
| 7 | mov(MMIO) | 命中 PCIe 结构中高延迟 GPU 寄存器 | 443,937,696 | 139 ms | AMD Ryzen 7 5800H |
| 4 | vmovdqu ymm | 32 字节 MMIO 读取 = 8 次 dword 事务 | 3,549,079,296 | 1.11 s | AMD Ryzen 7 5800H |
| 2 | fxrstor64(基线) | 从 MMIO 加载 512 字节 FPU 状态 | 74,584,168,512 | 23.3 s | AMD Ryzen 7 5800H |
| 1 | fxrstor64(冠军) | 基线 + 锤核饱和 PCIe 争用 | 198,002,498,236 | 62 s | AMD Ryzen 7 5800H |
图表的 Y 轴是对数刻度。线性刻度下,nop 的 1 个周期和冠军的 1980 亿个周期画在同一张图上根本看不出来。
冠军指令:fxrstor64 怎么跑出 62 秒的
fxrstor64 本身是一个普通的 x86 指令,功能是从内存恢复 512 字节的 FPU/MMX/XMM 处理器状态。在正常内存上执行,几十个周期就完事。
Domas 的做法是:把数据源换成 PCIe 总线上高延迟的 MMIO 寄存器。
具体步骤:
- 用 mmiotic 工具扫描 PCIe 地址空间,找到响应最慢的 GPU 寄存器区域
- 将 fxrstor64 的目标地址指向这片 MMIO 空间
- CPU 必须 512 字节全部从 PCIe 总线读取,每次读取都是一次 non-posted 事务(CPU 发出请求后必须等设备应答)
冠军版本更进一步:在 fxrstor64 执行的同时,用其他核心("锤核")疯狂读取另一片高延迟 MMIO 寄存器,把 PCIe root complex 和端点设备的处理能力全部占满。结果 CPU 0 的 512 字节 fxrstor64 被堵在队列后面排队,62 秒才执行完。
这揭示了 x86 架构的一个根本特性:指令的执行时间没有上限。当一条指令的内存操作数指向 MMIO 空间时,它的延迟取决于 PCIe 总线另一端设备的响应速度。GPU 的某些寄存器响应极慢,而 x86 指令集没有机制让指令在等待 IO 时提前放弃。
从微码到 PCIe:慢指令的三种来源
排行榜上的指令按变慢的机制可以分为三类:
微码 assist 路径(排名 22-17):CPU 执行浮点指令时遇到非规格化数(denormal),硬件无法直接处理,交由微码处理。微码需要归一化操作数、执行运算、再恢复处理器状态,周期数从正常几个周期暴涨到数百。fsin(257 周期)、fadd(677 周期)、fdiv(883 周期)都属于这类。
系统总线争用(排名 16, 13, 12):split lock 通过跨缓存行边界的原子操作强制 CPU 锁住外部总线,放弃 MESI 缓存一致性快路径。rdrand 的策略更巧妙——在紧密循环中不断调用,耗尽硬件熵池后后续调用被迫等待熵源恢复。wrmsr 写 MCG_CTL 寄存器时,AMD Zen 架构需要同步所有硬件单元的错误状态,涉及跨芯片通信。
PCIe MMIO 事务(排名 7-1):这是最暴力也最有效的方法。所有排名前七的指令都通过指向 PCIe 结构中的 GPU 寄存器来获取极高延迟。指令本身(mov、vmovdqu、fxrstor64)完全合法,但操作数地址指向了响应极慢的设备寄存器,CPU 每次访问都必须等待 PCIe 总线往返。
从 8 字节的 mov rax(278 ms)到 32 字节的 vmovdqu ymm(1.1 秒),延迟随数据宽度线性增长,因为更大的读取会被拆分成更多 dword 事务,每个事务都要单独排队。
还没到极限
排行榜底部有一条标着 :finnadie: 的条目:xrstor64(AMX)。策略是利用 Sapphire Rapids 处理器的扩展 AVX 状态区域——xsave 状态区 8KB,是 fxrstor64 的 512 字节的 16 倍。按比例推算,理论周期数会达到 1 万亿级别。条目标注 Contender: TODO,还没找到愿意跑的硬件。
项目同时开放了 ARM 和 RISC-V 排行榜,目前为空。
为什么有人关心最慢的指令
Domas 此前的工作包括 sandsifter(x86 处理器模糊测试工具)和 rosenbridge(发现某些 x86 CPU 中的硬件后门核心)。他的研究始终围绕一个方向:x86 架构中那些被忽略、未文档化、或者从未被认真测试的角落。
Assembly Hall of Shame 的排名第七 vmovdqu ymm (unaligned) 被标注为 "honorable mention"——这条非对齐的 256 位向量加载指令,通过迫使 GPU 寄存器发起 non-posted dword 事务,此前已被用于攻破系统管理模式(SMM)。一条普通的数据搬运指令,因为命中了 PCIe 结构中不该命中的地方,变成了绕过 CPU 特权级的攻击路径。
这说明 CPU 指令的"延迟"不只是一个性能数字。当一条指令的执行时间取决于外部设备响应时,它同时也取决于谁控制了那个外部设备。
来源:Assembly Hall of Shame (GitHub) · 作者 Christopher Domas (@xoreaxeaxeax)