Halt and Catch Fire: Câu chuyện về mã lệnh "bốc cháy" và lịch sử phần cứng

Công nghệ16 tháng 5, 2026·8 phút đọc

Halt and Catch Fire (HCF) không chỉ là tên một bộ phim truyền hình, mà còn là một thuật ngữ kỹ thuật vui đùa ám chỉ những mã lệnh khiến CPU ngừng hoạt động. Bài viết này khám phá nguồn gốc của HCF, trường hợp thực tế trên vi xử lý Motorola 6800 và cách các kỹ sư tận dụng lỗi phần cứng này.

Halt and Catch Fire: Câu chuyện về mã lệnh "bốc cháy" và lịch sử phần cứng

Tôi chưa bao giờ xem bộ phim "Halt and Catch Fire" của AMC, và trong một thời gian dài, tôi chỉ biết đến cái tên của nó mà không hiểu rõ nội dung. Có điều gì đó ở cái tên này luôn gợi nhớ đến những trò đùa của dân lập trình: một chút kịch tính, một chút phi lý và lại kỳ lạ đến mức chính xác. Hóa ra, bộ phim thực sự nói về ngành công nghiệp máy tính vào thập niên 1980 và 1990, nhưng chính cụm từ này còn lâu đời hơn bộ phim rất nhiều, và nó bắt nguồn từ những trò đùa trong giới kỹ thuật.

Ý nghĩa thực sự

Trong bối cảnh máy tính, Halt and Catch Fire (viết tắt là HCF) được dùng để mô tả mã máy (machine-code) khiến CPU ngừng thực hiện mọi tác vụ hữu ích, buộc bạn phải khởi động lại (hoặc tắt bật nguồn) máy để khôi phục. Theo nghĩa đen, nó làm máy "dừng lại". Phần "bốc cháy" (catch fire) chắc chắn là một trò đùa, nhưng nó không hề vô lý như bạn nghĩ. Hãy lấy hệ thống IBM System/360 làm ví dụ. Rõ ràng, khi hệ thống này gặp một mã thao tác (opcode) không hợp lệ nhất định, nó sẽ liên tục truy cập vào một vị trí cụ thể trong bộ nhớ từ tính (magnetic core memory), khiến vị trí đó trở nên rất nóng và thậm chí có thể bốc cháy.

Theo thời gian, HCF trở thành cái tên chung cho các opcode chưa được tài liệu hóa hoặc không hợp lệ làm treo bộ xử lý, các chế độ thử nghiệm có chủ đích trông giống như bị treo, và các lỗi phần cứng thực sự (có thể bạn còn nhớ một số chip Pentium đời đầu có thể bị treo bởi một lệnh bất hợp pháp được chọn kỹ lưỡng, được gọi là lỗi F00F - nhưng chúng ta sẽ nói kỹ hơn về điều này sau).

Cụm từ này được tạo ra một phần là do tiêu chuẩn sử dụng các cách viết tắt 3 chữ cái trong ngôn ngữ Assembly: ADD, CMP, JMP, v.v. Trò đùa này lan rộng trong các ấn phẩm khác nhau, bao gồm cả HCF cùng với một số cái tên ưa thích khác của tôi:

  • EPI: Execute Programmer Immediately (Thi hành lập trình viên ngay lập tức)
  • DC: Divide and Conquer (Chia để trị)
  • CRN: Convert to Roman Numerals (Chuyển đổi sang số La Mã)

Motorola 6800

Vậy ban đầu HCF chỉ là một trò đùa, cho đến khi nó không còn là trò đùa nữa.

Vi xử lý Motorola 6800 có 256 opcode một byte, nhưng không phải mọi mẫu bit đều tương ứng với một lệnh được tài liệu hóa. Nhấn phải mã lệnh và con chip sẽ làm bất cứ điều gì mà phần silic "giải mã" ra — đôi khi là không có gì đáng kể, đôi khi lại là điều gì đó quan trọng.

Bài viết của Gerry Wheeler trên tạp chí BYTE mang tên "Undocumented M6800 Instructions" (Các lệnh M6800 chưa được tài liệu hóa) được xuất bản vào tháng 12 năm 1977, số 2 tập 12, tại Diễn đàn Kỹ thuật trang 46-47. Ông bắt đầu từ tài liệu của chính Motorola: 197 opcode được tài liệu hóa, để lại 59 mẫu bit không được nhắc đến trong tài liệu chính thức. Một số trong số đó hoạt động giống như lệnh NOP (No Operation), một số thay đổi thanh ghi mã điều kiện theo các mẫu mà Wheeler nói là vẫn "chưa được giải mã" vào thời điểm đó, và hai byte — $9D và $DD — chia sẻ một kết quả đặc biệt tồi tệ mà ông chọn gọi là Halt and Catch Fire. Ông khẳng định rõ rằng "Các cách viết tắt này, tất nhiên là do tôi đặt".

Về mặt phần cứng, những gì thực sự xảy ra là phần này ngừng hoạt động như một động cơ lấy mã – giải mã – thực thi bình thường: bộ đếm chương trình tiếp tục tăng lên và con chip phát ra các lệnh đọc trong khi các đường địa chỉ chạy qua bộ nhớ giống như một bộ đếm phần cứng. Các ngắt không thể ngăn bạn thoát khỏi con đường tự hủy này — bạn chỉ có thể thoát khỏi vòng lặp bằng cách reset hoặc tắt bật nguồn. Mô tả của chính Wheeler rất đáng đọc nguyên văn thay vì diễn giải:

Khi lệnh này được chạy, cách duy nhất để xem nó đang làm gì là bằng máy hiện sóng. Theo góc độ của người dùng, máy dừng lại và chống lại hầu hết các nỗ lực khởi động lại nó. Những người có đèn báo trên bus địa chỉ sẽ thấy rằng bộ xử lý bắt đầu đọc toàn bộ bộ nhớ, một cách tuần tự, rất nhanh. Về hiệu quả, bus địa chỉ biến thành một bộ đếm 16 bit. Tuy nhiên, bộ xử lý không chú ý đến những gì nó đang đọc... nó chỉ đọc thôi.

Về phần "bốc cháy" của cụm từ, ông thêm vào, "À, thì gần như là vậy." Trong khi hệ thống của IBM thực sự có thể bốc cháy trong một số trường hợp, có vẻ như Motorola 6800 thì không.

Ngoài tạp chí BYTE, họ opcode này còn có các biệt danh khác. David J. Agans, trong cuốn sách Debugging (2002), nhớ lại mã DD là lệnh "Drop Dead" (Ngã xuống chết) mà nhóm của ông gọi — cùng thủ thuật chạy bus đó, nhưng tên khác — và lưu ý rằng các kỹ sư đã sử dụng nó có chủ đích vì "tất cả các đường địa chỉ và đường xung nhịp đều là các sóng vuông đẹp mắt, tuần hoàn" trên máy hiện sóng.

Hầu hết các máy chỉ có vẻ như bị treo. Ít nhất trên một máy vi tính 6800 đời đầu có bộ nhớ ánh xạ video (memory-mapped video) khó tính, mẫu này có thể xuất hiện dưới dạng "tuyết" (snow) hiển thị được. Bài viết Sphere News của Ben Z là một chủ đề rất thú vị để đào sâu (trọng tài video RAM, thời gian, hiện vật CRT).

Nhiều năm sau, các kỹ sư của Motorola đã viết thêm về vấn đề này. Trong IEEE Design & Test (1985), Daniels và Bruce mô tả một opcode bất hợp pháp mà khách hàng tìm thấy trên MC6800, có biệt danh nội bộ là HACOF, trong đó bộ đếm chương trình có thể tăng mãi mãi cho đến khi được reset. Họ cũng kể về một chi tiết gần như khó tin: kỹ sư sản phẩm muốn một cách nhanh chóng để quét RAM trong quá trình khởi động (bring-up), nhận thấy hành vi này đã làm được điều gì đó tương tự, và về cơ bản đã giữ nguyên nó thay vì tốn chi phí để loại bỏ nó. Vì vậy, theo lời của Bob Ross, đây hóa ra là một "tai nạn hạnh phúc".

Gần đây, có người thực sự đặt một con MC6800 thực lên phần cứng và thực sự đo lường nó thay vì chỉ tin vào các bản quét tạp chí cũ và trang Wikipedia. Bài viết phòng thí nghiệm của Doc TB lưu ý một chi tiết thú vị: sau khi opcode được lấy, có độ trễ khoảng hàng chục mili-giây trước khi các đường địa chỉ ổn định thành mẫu đếm nhanh nổi tiếng, và có các opcode chưa được tài liệu hóa khác trông giống như các phiên bản chậm hơn hoặc bị lỗi hơn của cùng một ý tưởng.

Vượt ra ngoài Motorola

Motorola không phải là bộ xử lý hiện đại duy nhất gặp vấn đề này: các opcode bất hợp pháp của 6502 làm treo CPU, lỗi F00F của Pentium (nếu bạn nhớ kỷ nguyên đó), các cặp lệnh trên một số kiến trúc chờ đợi mãi mãi một ngắt không thể đến, và các bài thuyết trình về fuzzing x86 hiện đại nơi mọi người vẫn tìm ra các trạng thái không hợp lệ trong các bộ xử lý khổng lồ.

Về cơ bản, với fuzzing, họ đang cố gắng đặt dữ liệu ngẫu nhiên hoặc không mong muốn vào bộ xử lý để giúp xác định các lỗ hổng hoặc lỗi trong bộ xử lý. Không ngạc nhiên, đây là một chiến lược khá hiệu quả, không chỉ với bộ xử lý mà với mọi loại phần mềm.

Dừng lại và kết thúc bài viết

Đây là một mẩu lịch sử thú vị để nghiên cứu — và hóa ra có nhiều điều hơn tôi mong đợi, thậm chí cả về phần "bốc cháy". Khi rất nhiều phần mềm chuyển lên các tầng cao hơn (higher stack), rất dễ để mất dấu phần cứng từ góc nhìn vĩ mô. Cuối cùng, nó chỉ là một cục silic được kết nối với nhau theo một cách đôi khi có thể sai sót.

Tôi chỉ biết rằng cụm từ này quá hay để không sử dụng — hãy mong đợi một dự án (hoặc công ty) trong tương lai sẽ sử dụng viết tắt "HCF".

Nguồn và thêm thông tin

Để bạn bận rộn, dưới đây là một số liên kết đến nguồn và thêm thông tin:

  • Gerry Wheeler, "Undocumented M6800 Instructions," BYTE Dec 1977
  • David J. Agans, Debugging: The Nine Indispensable Rules for Finding Even the Most Elusive Software and Hardware Problems (AMA, 2002), tr. 77
  • Ben Z, "Sphere News: Halt and Catch Fire!"
  • RetroComputing SE #15289
  • Doc TB, "Investigating the HCF instruction on Motorola 6800"
  • Wikipedia: Halt and Catch Fire (computing)
Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗