1 điểm bởi GN⁺ 1 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • ROM microcode của 80386 có kích thước 94.720 bit, lớn hơn nhiều so với 10.752 bit của 8086 nên việc chuyển đổi ảnh và kiểm chứng khó khăn hơn hẳn
  • Từ ảnh die độ phân giải cao, nhóm nghiên cứu đã kết hợp xử lý ảnh, mạng nơ-ron và tự động hóa có con người hỗ trợ để trích xuất blob nhị phân và đối chiếu chéo chỉ trong vài ngày
  • Trong quá trình dịch ngược, dần lộ ra cấu trúc mảng μ-op, các trường bit, mẫu kết thúc lệnh, bộ giải mã lệnh và cấu trúc PLA kiểm tra bảo vệ
  • 80386 có microcode tương ứng cho mọi lệnh, và nhiều routine chủ yếu dùng để cấu hình phần cứng nhân/chia và barrel shifter hơn là cài đặt thuật toán
  • Một lỗi tiềm tàng đã được phát hiện trong xử lý bitmap quyền IO ở protected mode: với truy cập cổng 4 byte, có vẻ chỉ 3 địa chỉ đầu tiên được kiểm tra, nhưng điều này vẫn chưa được xác nhận

Trích xuất và dịch ngược microcode của 80386

  • Sau bài dịch ngược microcode 8086, Ken Shirriff đã cung cấp ảnh độ phân giải cao của ROM microcode 80386, nhưng ROM của 80386 có 94.720 bit, lớn hơn rất nhiều so với 10.752 bit của 8086 nên việc chuyển đổi và kiểm chứng khó hơn nhiều
  • 8086 có bằng sáng chế mô tả cấu trúc tổng thể và một số mảnh mã nên còn có đầu mối để tìm kiếm, trong khi 80386 gần như là một hộp đen hoàn toàn, khiến việc tìm cấu trúc trong một khối nhị phân lớn trở nên khó khăn
  • Trên Discord, GloriousCow, Smartest Blob và những người khác đã tiếp tục công việc trích xuất microcode từ ảnh độ phân giải cao của die 80386; trở ngại lớn nhất là biến đổi từ ảnh → nhị phân → microcode có thể hiểu được
  • Bằng cách kết hợp xử lý ảnh, mạng nơ-ron và tự động hóa có con người hỗ trợ, họ đã trích xuất blob nhị phân từ ảnh chỉ trong vài ngày và đối chiếu chéo kết quả

Cấu trúc lộ ra trong quá trình dịch ngược

  • Ngay cả sau khi trích xuất được dữ liệu nhị phân, việc dịch ngược vẫn không hề dễ; bằng cách dò khớp nhiều mẫu khác nhau, họ tìm ra cách sắp xếp lại sao cho một trục là μ-op và trục còn lại là các bit μ-op
  • Việc có một khối μ-op không dùng đến nằm ở một đầu đã trở thành manh mối để xác định thứ tự đọc μ-op
  • Khi chia các bit μ-op thành nhiều trường, kinh nghiệm từ công việc trên microcode 8086 đã giúp xác định các trường thanh ghi nguồn và thanh ghi đích
  • Vì 80386 có thể thực hiện phép toán ALU trong 2 chu kỳ, nên cần một trường để chỉ định đầu vào thứ hai của ALU: chu kỳ đầu nạp hai toán hạng vào ALU, chu kỳ sau gửi kết quả tới đích
  • Những mẫu lặp đi lặp lại được suy đoán là dấu hiệu kết thúc lệnh, và sau đó được xác nhận là đúng
  • Ken đã góp phần lần theo nhiều dây dẫn và bit logic trên die 80386 để hiểu cách kết nối bên trong, và những cấu trúc mới được phát hiện lại trở thành đầu mối để giải thích các mảnh microcode khác dùng cùng thành phần
  • Cùng với microcode, bộ giải mã lệnh gồm nhiều PLA nhỏ và PLA kiểm tra bảo vệ cũng được giải mã, cho phép liên kết các lệnh 386 với các mảnh microcode tương ứng

Cách thực thi của 80386 khác 8086

  • 80386 nhanh hơn 8086 rất nhiều trên mỗi chu kỳ với phần lớn lệnh, và để làm được điều đó nó sử dụng nhiều transistor hơn
  • Nhiều thuật toán từng được cài bằng microcode trên 8086 nay được đảm nhiệm bởi các bộ tăng tốc phần cứng trên 80386
  • Phần đáng kể của microcode 80386 không làm chính thuật toán mà chủ yếu cấu hình các bộ tăng tốc như phần cứng nhân/chia, barrel shifter và khối kiểm tra bảo vệ
  • Một phần lớn công việc dịch ngược là tìm ra cách các giao diện bộ tăng tốc này kết nối với microcode

Điểm vào microcode và xử lý lệnh

  • Số điểm vào microcode từ ROM giải mã là 215, tăng mạnh so với 60 của 8086
  • Sự gia tăng này không chỉ do thêm lệnh mới mà còn vì cùng một lệnh có thể được xử lý bằng routine khác nhau tùy toán hạng là thanh ghi hay bộ nhớ, CPU đang ở real mode hay protected mode, và có dùng tiền tố REP hay không
  • Danh sách đầy đủ mọi entry nằm trong tệp fields.txt, cùng với các subroutine và mã dùng chung
  • Nhiều routine microcode cấp cao chỉ làm rất ít việc rồi nhảy sang routine dùng chung với các điểm vào khác, nên khó hiểu ý nghĩa nếu chỉ nhìn vào kích thước của routine cấp cao
  • Vì bộ giải mã lệnh không chỉ dùng opcode để quyết định routine sẽ gọi, nên cũng khó mô tả cấu trúc chỉ bằng số lượng opcode mà mỗi entry point xử lý

Mọi lệnh đều được xử lý bằng microcode

  • Không giống 8086 hay CPU hiện đại, 80386 luôn thực thi μ-op, và mọi lệnh đều có microcode tương ứng
  • Đã xác nhận rằng không có lệnh nào nằm ngoài xử lý bằng microcode

Dấu vết của mã không dùng và xử lý ngoại lệ

  • Các routine từ 0x849 đến 0x856 được đánh dấu là unused? trong bản dịch ngược microcode và dường như không có entry point nào liên kết tới đó
  • Chưa thể khẳng định hoàn toàn chức năng chính xác của các routine này, nhưng chúng có nhiều điểm chung với routine #PF (PAGE_FAULT) từ 0x8e9 đến 0x8f5
  • Cả hai đều đặt mã lỗi cuối cùng của paging unit rồi tiếp tục với interrupt 0x0e
  • Điểm khác biệt là routine này đặt CR2 bằng một giá trị không rõ lấy từ paging unit, thay vì địa chỉ tuyến tính gây lỗi
  • Phần microcode còn lại dường như được thiết kế để triển khai hành vi đã được tài liệu hóa của CPU, còn các routine tương tác với phần cứng ICE (In-Circuit Emulator) phục vụ gỡ lỗi mức thấp thì thuộc nhóm hành vi không được tài liệu hóa

Tính năng ẩn và lỗi có thể có trong bitmap quyền IO

  • Dù chưa thể xác nhận vì chưa thử trên máy 386 thực tế, có khả năng tồn tại lỗi trong xử lý bitmap quyền IO, cơ chế từng được một số HĐH ở protected mode dùng để cho phép có chọn lọc tiến trình user mode truy cập cổng IO
  • Khi xảy ra truy cập cổng 4 byte, microcode có vẻ chỉ kiểm tra bit quyền của 3 địa chỉ đầu tiên
  • Nếu tiến trình thực hiện kiểu truy cập này ở ranh giới của vùng cổng IO mà nó được cấp quyền, truy cập byte cuối có thể thành công sai lệch và chạm tới thanh ghi phần cứng mà HĐH không định cho user truy cập
  • Đây là một trường hợp rất đặc biệt nên có thể đã bị bỏ sót nếu không có bản dịch ngược microcode, nhưng việc một lỗi bảo mật trong phần cứng được dùng rộng rãi hơn 40 năm vẫn chưa từng bị phát hiện là điều khá bất thường
  • Hành vi này có thể chỉ xuất hiện trên một số phiên bản CPU, hoặc cũng có thể việc diễn giải routine đang sai và phần cứng thực tế vẫn hoạt động đúng
  • Bản microcode này có vẻ không thuộc các phiên bản đầu tiên của 80386, và các lệnh XBTS cùng IBTS không còn dấu vết nào ngoài phần decoder

Tài liệu học tập và nơi tải xuống

1 bình luận

 
Ý kiến trên Hacker News
  • Tò mò không biết có thể khôi phục microcode từ ảnh die độ phân giải cao bằng cách nào
    Không rõ quá trình này có phải là nhận diện từng transistor rồi mô hình hóa mạch hay không, và kết quả đầu ra có ở dạng như Verilog hay không

    • Tôi có tham gia một chút vào quá trình trích xuất; trước tiên, chúng tôi đánh dấu tọa độ x,y của mọi bit dựa trên vị trí giao nhau giữa các hàng và cột của mảng microcode
      Sau đó phân loại 0 và 1; số 1 có thể phân biệt bằng mắt nhờ sự hiện diện của transistor và khe hở trong polysilicon
      Do đặc tính microcode của Intel, có thể giả định rằng số 0 nhiều hơn hẳn, nên cứ nơi nào có transistor thì xem là 1
      Cũng có công cụ tự động xử lý bằng ngưỡng màu, nhưng một phần ảnh ghép bị mờ và có bụi nên sinh ra rất nhiều bit 1 giả, thành ra không ổn lắm
      Thay vào đó, chúng tôi huấn luyện một mạng nơ-ron tích chập để phân loại các vùng bit đã trích xuất thành 0/1, rồi kiểm tra kết quả bằng cách phủ các hình chữ nhật trắng/đen với độ trong suốt 50% lên ảnh ghép gốc
      Sau đó mất vài ngày rà soát lỗi khá tẻ nhạt, và cuối cùng thu được mảng bit 2 chiều thô; bước tiếp theo là trích các từ microcode từ mảng đó
    • Có một video bóc tách chip cơ chế lockout của Nintendo 64 theo từng lớp, và nó đi khá sâu vào kiểu công việc này theo nhiều cách khác nhau
      https://youtu.be/HwEdqAb2l50?si=VFLed64PZvpCHfy1
    • Chỉ cần nhìn vào chính bức ảnh
      “Ảnh trên cho thấy một phần ROM microcode. Khi nhìn qua kính hiển vi, có thể thấy nội dung của ROM microcode, và có thể đọc ra bit tùy theo việc tại mỗi vị trí có hay không có transistor”
      https://www.righto.com/2020/06/a-look-at-die-of-8086-process...
    • Microcode nằm trong ROM, với cấu trúc đều đặn nơi 1 và 0 trông khác nhau
  • Chủ đề liên quan đang được thảo luận: z386: An Open-Source 80386 Built Around Original Microcode - https://news.ycombinator.com/item?id=48248014 - Tháng 5 năm 2026, 22 bình luận

  • Vài ngày trước khi kiểm tra blog reenigne, tôi đã nghĩ kiểu “ờ, từ 2020 đến giờ không có bài nào nhỉ”, nên thấy blog hoạt động lại thật vui
    Việc blog này còn lưu dấu đến tận 33 năm trước cũng đặc biệt thú vị

    • Có khi bộ đếm lượt xem tăng lên đã trở thành động lực để viết bài
  • Một cuốn sách hay giải thích microprogramming từ nền tảng: https://www.amazon.com/Computation-Structures-Optical-Electr...
    Bản PDF miễn phí cũng khá dễ tìm

  • Công sức cần thiết để reverse engineer microcode này thật ấn tượng, và đây là một bài viết tuyệt vời đào sâu vào kiến trúc 386

  • Khi nhìn vào phần triển khai microcode thực tế, cách các bộ xử lý cũ xử lý các phép toán phức tạp bỗng bớt huyền bí hơn

  • 386 đã có rất nhiều thay đổi nhỏ trong suốt 22 năm sản xuất, nên điều quan trọng là biết đoạn mã này đến từ revision 386 nào

    • Một manh mối là giá trị được nạp vào EDX lúc reset
      9B5 BIST1 -> TMPD 0x0303 PASS2
      9B6 SIGMA -> EDX
      9B7 BIST2 -> TMPE TMPD XOR
      9B8 SIGMA 0x3ddc0c2c XOR
      9B9 SIGMA -> EAX BOOTUP_JUMP JFPUOK
      0x303 có nghĩa là family 3, model 0, stepping ID 3
  • Phần phân tích hộp đen cần thiết để giải mã thứ này hẳn là cực kỳ khó, nhưng nếu thành công thì chắc sẽ rất thú vị và xứng đáng

  • Thật mãn nguyện khi từng học những môn khó ở đại học để có thể hiểu được các bài như thế này, và cũng vui vì HN hồi năm 2015 đã khơi gợi kiểu tư duy đó
    Giờ đây dù không còn dùng nhiều kiến thức lập trình mức thấp, mỗi lần đọc những bài kiểu này tôi vẫn có cảm giác ý thức của mình được mở rộng, rất tuyệt
    Với những ai khó tiếp cận đại học, tôi gợi ý nand2tetris.org

    • Tự tay xây dựng một microprocessor từ các cổng logic là cách dễ hơn để hiểu thiết kế microcode và cách bộ xử lý vận hành
      Học các thiết kế cũ đơn giản như RISC hay Transputer cũng hữu ích, còn 80386 thì nằm ở đầu đối diện của phổ đó
      Nó trở nên phức tạp không cần thiết vì phải duy trì các thiết kế cũ tệ và khả năng tương thích ngược
      Để học thiết kế chip thì không nhất thiết phải vào đại học; xem vài bài nói chuyện của Alan Kay hoặc đọc qua tài liệu thiết kế máy tính trên Bitsavers cũng là khởi đầu tốt
      Tôi đã tạo ra Morphle Logic, cho phép mô phỏng thiết kế mức cổng theo cách dễ hơn FPGA và chuyển nó thành transistor trên chip với chi phí dưới 200 USD theo mặt bằng năm 2026
      Cuối cùng điều đó có thể dẫn đến việc tích hợp siêu máy tính quy mô wafer ngày càng lớn hơn, nhanh hơn và rẻ hơn
      https://github.com/fiberhood/MorphleLogic/blob/main/README_M...
      https://www.youtube.com/watch?v=vbqKClBwFwI
      https://www.youtube.com/watch?v=f1605Zmwek8
      http://bitsavers.informatik.uni-stuttgart.de/pdf/xerox/alto/...
    • Tôi đã thử nand2tetris vài lần, nhưng vì nó nhấn mạnh sự đơn giản ở mọi mức trừu tượng nên bỏ qua những thứ như microcode
      Bản thân sự đơn giản đó là một bài học tuyệt vời và đã truyền nhiều cảm hứng cho tôi, nhưng các lớp kỹ thuật điện tôi học ở đại học vào thập niên 1990 cũng tương tự nand2tetris ở chỗ trình bày cách CPU kiểu 8086 được tạo ra, đồng thời vẫn giải thích cách microcode hoạt động
      Bộ đếm chương trình nội bộ sẽ đi theo bảng từ điều khiển, và mỗi bit sẽ trực tiếp điều phối một phần có thể điều khiển được của CPU
      Mỗi người trong lớp tự cài đặt một lệnh trong trình mô phỏng; tôi phụ trách DEC, tức lệnh giảm
      Ở một khía cạnh nào đó, cũng có thể xem các lệnh của nand2tetris là microcode
      Các bit của lệnh điều khiển trực tiếp phần cứng và bit đầu tiên chọn giữa hai loại lệnh, nên mỗi lệnh chỉ có 1 bước mã
      Trong khi đó, với microcode, một lệnh có thể có số bước microcode tùy ý
      Trong loạt video CPU 8-bit trên breadboard của Ben Eater, ROM được đánh chỉ mục bằng opcode 4 bit của lệnh và bộ đếm bước để quyết định từ điều khiển
      ROM này thay cho phần mà lẽ ra cũng có thể được tạo bằng các cổng logic đủ phức tạp; vì phải trực tiếp đụng vào điện tử và tự xử lý vấn đề nên đây là bước tiếp theo khá tốt về phía phần cứng
      Chỉ tiếc là RAM chỉ có 16 byte, nên khó xây dựng các tầng trừu tượng cao hơn như nand2tetris
      Đến lúc đó, bạn có thể làm lại với thiết kế tốt hơn, đưa lên PCB, hoặc chuyển sang dự án 6502 để suy nghĩ về timer, CPU, ROM, RAM, I/O, UART v.v. như một thể thống nhất, rồi tiếp tục sang các vi điều khiển vốn đã tích hợp sẵn những thứ đó
      Nếu muốn đọc về cách tạo CPU từ các cổng logic, Code của Charles Petzold giải thích chậm rãi và mới được tái bản gần đây, còn Pattern on the Stone của Danny Hillis thì đi nhanh hơn
      Ấn bản 2 của Code dùng bộ đếm chu kỳ 4 bit và logic hardwired để quyết định hoạt động ở từng chu kỳ, đồng thời dùng mảng diode cho một phần logic; tôi cũng tự hỏi liệu cái đó có nên được xem là microcode không
    • Tôi tò mò liệu nand2tetris có đề cập hoặc sử dụng microcode hay không