Halt and Catch Fire: 'Illegal Opcode'의 역사

오늘날 많은 이들이 Halt and Catch Fire를 개인용 컴퓨터 혁명에 관한 비평가들의 찬사를 받은 AMC 시리즈로 알고 있지만, 이 문구는 훨씬 더 오래된 공학 유머와 하드웨어 불안정성의 전통에서 유래되었습니다. 컴퓨팅 초기 시절, "Halt and Catch Fire" (HCF)는 CPU가 유용한 작업을 수행하는 것을 중단하게 만들어, 운영자가 기계를 재부팅(power-cycle)하는 것 외에는 선택의 여지가 없게 만드는 머신 코드를 일컫는 약어로 사용되었습니다.

'Illegal Opcode'의 구조

HCF의 핵심은 프로세서가 문서화되지 않았거나 유효하지 않은 opcode—하드웨어가 처리 방법을 모르는 비트 패턴—를 만나는 상태를 설명합니다. 완벽하게 설계된 시스템이라면 유효하지 않은 opcode는 예외(exception)를 발생시키거나 제어된 중단(halt)을 유도해야 합니다. 하지만 초기 실리콘 설계에서는 명령어 세트의 이러한 "구멍"들이 종종 예측 불가능한 동작을 초래했습니다.

역사적으로 이 문구는 표준적인 세 글자 어셈블리 mnemonic(예: ADD, CMP, 또는 JMP)을 활용한 언어유희이기도 했습니다. 이는 당시의 다른 프로그래머 유머들과 나란히 존재했습니다:

  • EPI: Execute Programmer Immediately
  • DC: Divide and Conquer
  • CRN: Convert to Roman Numerals

Motorola 6800과 'Bus-Walking' 버그

Motorola 6800의 경우, HCF는 농담에서 문서화된 하드웨어 특성으로 변모했습니다. 이 칩은 256개의 단일 바이트 opcode를 특징으로 했지만, 공식적으로 문서화된 것은 197개뿐이었습니다. 이로 인해 실리콘이 문서화되지 않은 방식으로 디코딩할 59개의 비트 패턴이 남게 되었습니다.

1977년 BYTE 매거진의 기사에서 Gerry Wheeler는 치명적인 실패를 유발하는 두 가지 특정 바이트—$9D$DD—를 식별했습니다. 이 opcode들이 실행될 때 프로세서는 fetch-decode-execute 엔진처럼 동작하기를 멈춥니다. 대신, 프로그램 카운터(program counter)가 무한히 증가하며, 칩은 주소 버스(address bus)를 통해 지속적인 읽기 요청을 보냅니다.

Wheeler가 설명한 내용은 다음과 같습니다:

이 명령어가 실행될 때 무엇을 하고 있는지 확인하는 유일한 방법은 오실로스코프를 사용하는 것입니다. 사용자 관점에서는 기계가 멈추고 재시작하려는 대부분의 시도를 거부합니다. 주소 버스에 표시등이 있는 사람들은 프로세서가 메모리의 모든 내용을 매우 빠르게, 순차적으로 읽기 시작하는 것을 보게 될 것입니다. 사실상 주소 버스가 16비트 카운터로 변하는 것입니다.

흥미롭게도, 이러한 동작은 항상 결함으로 간주되지는 않았습니다. Motorola 엔지니어들은 나중에 IEEE Design & Test (1985)에서 이 상태의 내부 별명이 HACOF였다고 밝혔습니다. 이 "bus-walking" 동작이 RAM을 효과적으로 스캔할 수 있었기 때문에, 제품 엔지니어링 팀은 버그를 제거하기 위해 자원을 소모하는 대신, 이를 초기 구동(bring-up) 과정에서 메모리를 테스트하는 빠른 방법으로 유지하기로 결정했습니다.

Core Memory에서 현대적 Fuzzing까지

문구의 "catch fire" 부분은 흔히 과장으로 여겨지지만, 물리적 실체에 뿌리를 두고 있습니다. 일부 기록에 따르면 IBM System/360에서는 특정 유효하지 않은 opcode가 자기 코어 메모리(magnetic core memory)의 특정 위치에 너무 빠르게 접근하게 만들어 하드웨어가 과열되어 실제로 불이 날 수도 있었다고 합니다. 일부 회의론자들은 이를 도시 전설로 보지만, 소프트웨어 오류로 인한 하드웨어 실패의 위험은 초기 컴퓨팅 시절의 실질적인 현실이었습니다.

다른 유사한 실패 사례들은 다양한 아키텍처에서 나타났습니다:

  • The 6502: CPU를 잠금(lock) 상태로 만들 수 있는 illegal opcode를 포함하고 있었습니다.
  • The Pentium F00F Bug: 특정 바이트 시퀀스가 프로세서를 잠금 상태로 만들 수 있는 유명한 결함입니다.
  • CRT Burn-in: Commodore PET 4032에서는 부적절한 POKE 명령어가 CRT 라스터 스캔을 중단시키고, 전자빔을 한 곳에 고정시켜 몇 분 만에 화면의 인phosphors를 태워버릴 수 있었습니다.

오늘날 이러한 유산산은 fuzzing의 형태로 이어집니다. 현대 보안 연구원들은 프로세서에 무작위 또는 예상치 못한 데이터를 입력하여 유효하지 않은 상태, 취약점 또는 하드웨어 버그를 식별별하는 데 fuzzing을 사용합니다. 이는 본질적으로 다음 HCF 명령어를 찾는 고도의 기술적 버전이라 할 수 있습니다.

하드웨어 시대에 대한 성찰

HCF에 대한 매혹은 소프트웨어와 하드웨어의 경 경계가 모호했던 시기를 반영합니다. 한 관찰자는 80년대와 90년대에 개발자가 "하드웨어를 직접 다루며, 하드웨어와 소프트웨어 모두가 무엇을 하고 있는지 대체로 이해할 수 있었던" 경이로움의 시대를 제공했다고 언급했습니다.

고수준 추상화와 클라우드 컴퓨팅의 시대인 오늘날, 모든 코드 한 줄이 결국 실리콘을 통해 움직이는 전기 신호로 변환된다는 사실을을 것을 잊기 쉽습니다. "Halt and Catch Fire"의 역사가 보여주듯, 논리적 오류와 물리적 재앙 사이의 거리는 우리가 생각하는 것보다 때로는 더 짧을 수 있습니다.

Sources