Halt and Catch Fire: '非法指令'的历史
虽然今天许多人将 Halt and Catch Fire 视为一部关于个人电脑革命、广受好评的 AMC 系列剧,但这个短语起源于更古老的工程幽默和硬件不稳定性的传统。在计算领域的早期,"Halt and Catch Fire" (HCF) 成为了机器码导致 CPU 停止执行有用工作的缩写,让操作员别无选择,只能通过重新启动机器来解决。
'非法指令'的解剖学
HCF 的核心在于描述了一种处理器遇到未记录或无效指令(opcode)的状态——即硬件不知道如何处理的位模式(bit pattern)。在一个设计完美的系统中,无效指令应该触发异常或受控的停机。然而,在早期的硅片中,这些指令集中的"洞"往往会导致不可预测的行为。
从历史上看,这个短语在一定程度上是对标准的三字母汇编助记符(如 ADD、CMP 或 JMP)的一种戏谑。它与那个时代的其他程序员笑话并列,例如:
EPI: Execute Programmer ImmediatelyDC: Divide and ConquerCRN: Convert to Roman Numerals
Motorola 6800 与 '总线漫游' 错误
对于 Motorola 6800 而言,HCF 从一个笑话转变为了一种记录在案的硬件特性。该芯片拥有 256 个单字节指令,但只有 197 个是官方记录的。这留下了 59 个硬件会以未记录的方式进行解码的位模式。
在 1977 年的 BYTE 杂志文章中,Gerry Wheeler 识别出了两个特定的字节——$9D 和 $DD——它们会触发灾难性的故障。当这些指令被执行时,处理器不再表现得像一个取指-译码-执行引擎。相反,程序计数器会无限增加,并且芯片会通过地址总线发出连续的读取请求。
正如 Wheeler 所描述的:
当运行此指令时,唯一的观察方法是使用示波器。从用户的角度来看,机器会停机并拒绝大多数重启尝试。那些在地址总线上装有指示灯的人会看到处理器开始非常快速地、顺序地读取所有内存。实际上,地址总线变成了一个 16 位计数器。
有趣的是,这种行为并不总是被视为缺陷。Motorola 的工程师后来在 IEEE Design & Test (1985) 中透露,这种状态的内部昵称是 HACOF。由于这种"总线漫游"行为实际上是在扫描 RAM,产品工程部门决定将其保留,作为在调试过程中快速测试内存的一种方式,而不是投入资源去修复这个错误。
从核心内存到现代模糊测试
短语中的"catch fire"(着火)部分通常被视为夸张,但它有着物理现实的根源。一些说法认为,在 IBM System/360 上,某些无效指令会导致系统极快地访问磁芯内存中的特定位置,以至于硬件会过热并发生物理着火。
虽然一些怀疑论者将其视为都市传说,但在早期计算领域,软件错误导致硬件故障的风险是真实存在的。
其他类似的故障也出现在各种架构中:
- The 6502: 具有可能锁定 CPU 的非法指令。
- The Pentium F00F Bug: 一个著名的缺陷,特定的字节序列可以锁定处理器。
- CRT Burn-in: 在 Commodore PET 4032 中,不当的
POKE命令可以停止 CRT 扫描,使电子束停留在某一点,并在几分钟内烧毁屏幕上的荧光粉。
今天,这种遗产以 fuzzing(模糊测试)的形式延续。现代安全研究人员使用 fuzzing 向处理器输入随机或意外的数据,以识别无效状态、漏洞或硬件错误——这本质上是寻找下一个 HCF 指令的高科技版本。
对硬件时代的思考
对 HCF 的着迷反映了一个时期,当时软件和硬件之间的界限是模糊的。正如一位观察者所言,80 年代和 90 年代提供了一种奇妙的感觉,开发者可以"接触到硬件,并能在很大程度上理解硬件和软件都在做什么。"
在这样一个高层抽象和云计算的时代,我们很容易忘记,每一行代码最终都会转化为在硅片中移动的电信号。正如 "Halt and Catch Fire" 的历史所证明的,逻辑错误与物理灾难之间的距离有时比我们想象的要短。