# 80386 마이크로코드 역어셈블됨

> Clean Markdown view of GeekNews topic #29829. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=29829](https://news.hada.io/topic?id=29829)
- GeekNews Markdown: [https://news.hada.io/topic/29829.md](https://news.hada.io/topic/29829.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-25T02:40:10+09:00
- Updated: 2026-05-25T02:40:10+09:00
- Original source: [reenigne.org](https://www.reenigne.org/blog/80386-microcode-disassembled/)
- Points: 1
- Comments: 1

## Topic Body

- **80386 마이크로코드 ROM**은 94,720비트로 8086의 10,752비트보다 훨씬 커서 이미지 변환과 검증이 까다로웠음
- 고해상도 다이 이미지에서 **이미지 처리·신경망·사람 보조 자동화**를 조합해 며칠 만에 바이너리 블롭을 추출하고 교차 검증함
- 역어셈블 과정에서 μ-op 배열, 비트 **필드**, 명령 종료 패턴, 명령 디코더와 보호 테스트 PLA 구조가 점진적으로 드러남
- 80386은 모든 명령에 대응하는 **마이크로코드**가 있으며, 많은 루틴은 알고리듬보다 곱셈·나눗셈 하드웨어와 배럴 시프터 설정을 담당함
- 보호 모드의 **IO 권한 비트맵** 처리에서 4바이트 포트 접근 시 처음 3개 주소만 검사하는 듯한 잠재 결함이 발견됐지만 아직 확정되지는 않음

---

### 80386 마이크로코드 추출과 역어셈블
- [8086 마이크로코드 역어셈블](https://www.reenigne.org/blog/8086-microcode-disassembled/) 이후 [Ken Shirriff](https://www.righto.com/)가 80386의 **마이크로코드 ROM** 고해상도 이미지를 제공했지만, 80386 ROM은 94,720비트로 8086의 10,752비트보다 훨씬 커 변환과 검증이 훨씬 어려웠음
- 8086에는 전체 구조와 일부 코드 조각을 담은 특허가 있어 검색 단서가 있었지만, 80386은 **완전한 블랙박스**에 가까워 큰 바이너리 덩어리에서 구조를 찾기 어려웠음
- Discord에서 GloriousCow와 Smartest Blob 등이 80386 다이의 고해상도 이미지에서 마이크로코드를 추출하는 작업을 이어갔고, 이미지→바이너리→이해 가능한 마이크로코드로 바꾸는 과정이 핵심 난관이었음
- 이미지 처리, 신경망, 사람 보조 자동화를 조합해 며칠 만에 이미지에서 **바이너리 블롭**을 추출하고 교차 검증함

### 역어셈블 과정에서 드러난 구조
- 바이너리 추출 뒤에도 역어셈블은 쉽지 않았고, 여러 패턴을 맞춰 가며 한 축에는 **μ-op**, 다른 축에는 μ-op 비트가 오도록 재배열하는 방식을 파악함
- 사용되지 않은 μ-op 블록이 한쪽 끝에 있어 μ-op을 읽는 순서를 파악하는 단서가 됨
- μ-op 비트를 여러 **필드**로 나누는 과정에서는 8086 마이크로코드 작업 경험을 바탕으로 소스 레지스터와 목적지 레지스터 필드를 찾아감
- 80386은 ALU 연산을 2사이클에 수행할 수 있으므로, 첫 번째 사이클에서 두 피연산자를 ALU에 적재하고 두 번째 사이클에서 결과를 목적지로 보내려면 ALU의 두 번째 입력을 지정하는 필드가 필요했음
- 반복적으로 나타나는 패턴은 명령의 끝을 나타내는 것으로 추정됐고, 이후 실제로 맞는 것으로 확인됨
- Ken은 80386 다이의 여러 선과 논리 비트를 추적해 내부 연결 방식을 파악하는 데 기여했고, 새로 밝혀진 구조는 같은 구성물을 쓰는 다른 마이크로코드 조각을 해석하는 단서가 됨
- 마이크로코드와 함께 여러 작은 PLA로 구성된 **명령 디코더**와 보호 테스트 PLA도 해독되면서 386 명령을 마이크로코드 조각과 연결할 수 있게 됨

### 8086과 다른 80386의 실행 방식
- 80386은 대부분의 명령에서 8086보다 사이클당 훨씬 빠르며, 이를 위해 더 많은 트랜지스터를 사용했음
- 8086에서 마이크로코드로 구현되던 여러 알고리듬은 80386에서 사실상 **하드웨어 가속기**가 맡음
- 80386 마이크로코드의 상당 부분은 알고리듬 자체보다 곱셈·나눗셈 하드웨어, 배럴 시프터, 보호 테스트 유닛 같은 가속기를 설정하는 역할을 함
- 역어셈블 작업의 큰 비중은 이러한 **가속기 인터페이스**와 마이크로코드 사이의 연결 방식을 파악하는 데 있었음

### 마이크로코드 엔트리와 명령 처리
- 디코딩 ROM에서 진입하는 마이크로코드 **엔트리 포인트**는 215개로, 8086의 60개보다 크게 늘었음
- 엔트리 증가는 새 명령 추가뿐 아니라 피연산자가 레지스터인지 메모리인지, CPU가 실모드인지 보호 모드인지, REP 접두사가 사용 중인지에 따라 같은 명령도 서로 다른 루틴으로 처리되기 때문임
- 모든 엔트리 목록은 `fields.txt` 파일에 있으며, 서브루틴과 공유 코드도 함께 들어 있음
- 많은 상위 마이크로코드 루틴은 적은 작업만 수행한 뒤 다른 엔트리 포인트와 공유하는 루틴으로 점프하므로, 상위 루틴의 크기만으로는 의미를 파악하기 어려움
- 명령 디코더가 사용할 루틴을 정할 때 opcode만 쓰지 않기 때문에, 각 엔트리 포인트가 처리하는 opcode 개수만으로도 구조를 설명하기 어려움

### 모든 명령은 마이크로코드로 처리됨
- 80386은 8086이나 현대 CPU와 달리 항상 **μ-op**을 실행하며, 모든 명령에 대응하는 마이크로코드가 있음
- 마이크로코드로 처리되지 않는 명령은 없는 것으로 확인됨

### 사용되지 않는 코드와 예외 처리 흔적
- `0x849`부터 `0x856`까지의 루틴은 마이크로코드 역어셈블에서 `unused?`로 표시되어 있으며, 연결된 엔트리 포인트가 없는 것으로 보임
- 이 루틴의 정확한 동작은 완전히 확실하지 않지만, `0x8e9`부터 `0x8f5`까지의 `#PF`(`PAGE_FAULT`) 루틴과 공통점이 많음
- 두 루틴 모두 paging unit의 마지막 오류 코드를 설정한 뒤 **interrupt 0x0e**로 이어짐
- 차이는 이 루틴이 fault linear address 대신 paging unit에서 나온 알 수 없는 값을 `CR2`에 설정한다는 점임
- 나머지 마이크로코드는 CPU의 문서화된 동작을 구현하도록 설계된 것으로 보이며, 저수준 디버깅용 **ICE(In-Circuit Emulator)** 하드웨어와 상호작용하는 루틴은 문서화되지 않은 동작에 해당함

### 숨겨진 기능과 가능한 IO 권한 비트맵 결함
- 아직 실제 386 머신에서 시험하지 못해 확정할 수는 없지만, 보호 모드 OS 일부가 사용자 모드 프로세스에 IO 포트 접근을 제한적으로 허용할 때 쓰던 **IO 권한 비트맵** 처리에 결함 가능성이 있음
- 4바이트 포트 접근이 발생할 때 마이크로코드는 처음 3개 주소의 권한 비트만 검사하는 것처럼 보임
- 프로세스가 권한을 가진 IO 포트 공간의 경계에서 이런 접근을 수행하면, 마지막 바이트 접근이 잘못 성공해 OS가 사용자 접근을 의도하지 않은 하드웨어 레지스터에 닿을 가능성이 있음
- 이 버그는 매우 특이한 경우라 마이크로코드 역어셈블 없이는 놓쳤을 수 있지만, 40년 넘게 널리 쓰인 하드웨어의 보안 버그가 발견되지 않았다는 점은 이례적임
- 해당 동작은 일부 CPU 버전에만 있었을 수도 있고, 루틴 해석이 잘못되어 실제로는 올바르게 동작할 수도 있음
- 이 마이크로코드는 80386 초기 버전의 것으로 보이지 않으며, `XBTS`와 `IBTS` 명령은 디코더를 제외하면 흔적이 없음

### 학습 자료와 다운로드 위치
- [nand2mario](https://nand2mario.github.io/)의 80386 내부 구조 글은 역어셈블을 이해하기 위한 출발점으로 유용함
- [80386 Multiplication and Division](https://nand2mario.github.io/posts/2026/80386_multiplication_and_division)
- [80386 Barrel shifter](https://nand2mario.github.io/posts/2026/80386_barrel_shifter/)
- [80386 Protection](https://nand2mario.github.io/posts/2026/80386_protection/)
- [80386 Memory Pipeline](https://nand2mario.github.io/posts/2026/803386_memory_pipeline/)
- 역어셈블 결과는 [GitHub의 x86 microcode 저장소](https://github.com/dbalsom/x86_microcode/tree/main/80386)에서 받을 수 있음
- `parts.txt`는 다른 파일들의 역할을 안내하며, `microcode_10.txt`는 마이크로코드 역어셈블 자체로 바로 들어가는 파일임

## Comments



### Comment 58159

- Author: neo
- Created: 2026-05-25T02:40:11+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=48247004) 
- 고해상도 **다이 이미지**에서 어떻게 마이크로코드를 복원할 수 있는지 궁금함  
  과정이 각 트랜지스터를 인식해서 회로를 모델링하는 건지, 결과물이 Verilog 같은 형태인지도 알고 싶음
  - 추출 과정에 조금 참여했는데, 먼저 **마이크로코드 배열**의 행과 열이 만나는 위치를 기준으로 모든 비트의 x,y 좌표를 표시함  
    그다음 0과 1을 분류하는데, 1은 트랜지스터 존재와 폴리실리콘의 틈으로 시각적으로 구분됨  
    Intel 마이크로코드 특성상 0이 훨씬 많다고 가정할 수 있어서, 트랜지스터가 있으면 1로 봤음  
    색상 임계값으로 자동 처리하는 도구도 있지만, 모자이크 일부가 흐리고 먼지가 들어가 **가짜 1비트**가 많이 생겨 잘 안 맞았음  
    대신 합성곱 신경망으로 추출한 비트 영역을 0/1로 분류하게 학습시키고, 결과를 원본 모자이크 위에 흰색/검은색 사각형 50% 불투명도로 덮어 확인했음  
    이후 며칠 동안 지루하게 오류를 검수했고, 최종적으로 원시 2차원 비트 배열을 얻었으며 다음 단계는 그 배열에서 마이크로코드 워드를 추출하는 것임
  - Nintendo 64 **락아웃 메커니즘** 칩을 층별로 벗겨내는 영상이 있고, 이런 작업을 여러 방식으로 꽤 깊게 다룸  
    [https://youtu.be/HwEdqAb2l50?si=VFLed64PZvpCHfy1](<https://youtu.be/HwEdqAb2l50?si=VFLed64PZvpCHfy1>)
  - 이미지 자체를 보면 됨  
    “위 사진은 마이크로코드 ROM 일부를 보여준다. 현미경으로 보면 마이크로코드 ROM의 내용이 보이고, 각 위치에 트랜지스터가 있는지 없는지에 따라 비트를 읽어낼 수 있다”  
    [https://www.righto.com/2020/06/a-look-at-die-of-8086-process...](<https://www.righto.com/2020/06/a-look-at-die-of-8086-processor.html>)
  - 마이크로코드는 **ROM**에 들어 있고, 1과 0이 다르게 보이는 규칙적인 구조임

- 관련 진행 중 스레드: z386: An Open-Source 80386 Built Around Original Microcode - [https://news.ycombinator.com/item?id=48248014](<https://news.ycombinator.com/item?id=48248014>) - 2026년 5월, 댓글 22개

- 며칠 전 reenigne 블로그를 확인했을 때는 “음, 2020년 이후 글이 없네” 싶었는데, 다시 올라와서 반가움  
  블로그가 **33년 전**까지 거슬러 올라가는 것도 특히 재미있음
  - 조회수 카운터가 올라간 게 글을 쓰는 계기가 됐을지도 모름

- 마이크로프로그래밍을 기초부터 설명하는 좋은 책: [https://www.amazon.com/Computation-Structures-Optical-Electr...](<https://www.amazon.com/Computation-Structures-Optical-Electro-Optical-Engineering/dp/0070681473>)  
  무료 PDF도 쉽게 찾을 수 있음

- 이 마이크로코드를 **리버스 엔지니어링**하는 데 필요한 노력이 인상적이고, 386 아키텍처를 깊게 파고든 훌륭한 글임

- 실제 **마이크로코드 구현**을 보면 오래된 프로세서가 복잡한 연산을 어떻게 처리했는지 덜 신비롭게 느껴짐

- 386은 22년 생산 기간 동안 작은 변경이 많았기 때문에, 이 코드가 어느 **386 리비전**에서 나온 것인지 아는 게 중요함
  - 한 가지 단서는 리셋 시 EDX에 로드되는 값임  
    `9B5 BIST1 -> TMPD 0x0303 PASS2`  
    `9B6 SIGMA -> EDX`  
    `9B7 BIST2 -> TMPE TMPD XOR`  
    `9B8 SIGMA 0x3ddc0c2c XOR`  
    `9B9 SIGMA -> EAX BOOTUP_JUMP JFPUOK`  
    `0x303`은 제품군 3, 모델 0, 스테핑 ID 3을 뜻함

- 이걸 해독하는 데 필요한 **블랙박스 분석**은 엄청 어렵지만, 성공하면 굉장히 재미있고 보람도 클 것 같음

- 이런 글을 이해하려고 대학에서 어려운 과목을 들었던 게 만족스럽고, 2015년 당시 HN이 그런 사고를 자극해준 것도 좋았음  
  지금은 저수준 프로그래밍 지식을 크게 쓰지 않더라도, 이런 글을 읽을 때마다 의식이 풍부해지는 느낌이 들어 멋짐  
  대학에 접근하기 어려운 사람에게는 nand2tetris.org를 추천함
  - 게이트부터 직접 **마이크로프로세서**를 만들어보는 것이 마이크로코드 설계와 프로세서 동작을 이해하는 더 쉬운 방법임  
    단순한 예전 설계인 RISC나 Transputer를 공부해도 도움이 되고, 80386은 그 스펙트럼의 반대편에 있음  
    오래된 나쁜 설계와 하위 호환을 유지하려다 불필요하게 복잡해졌기 때문임  
    칩 설계를 배우는 데 꼭 대학이 필요한 것은 아니고, Alan Kay 강연을 몇 개 보거나 Bitsavers의 컴퓨터 설계를 훑어보는 것도 좋은 출발점임  
    FPGA보다 쉬운 방식으로 게이트 수준 설계를 시뮬레이션하고 2026년 기준 200달러 미만으로 칩 위 트랜지스터로 변환하는 Morphle Logic을 만들었음  
    결국 더 커지고 빨라지며 저렴한 **웨이퍼 규모 슈퍼컴퓨터** 통합으로 이어질 수 있음  
    [https://github.com/fiberhood/MorphleLogic/blob/main/README_M...](<https://github.com/fiberhood/MorphleLogic/blob/main/README_MORPHLE_LOGIC.md>)  
    [https://www.youtube.com/watch?v=vbqKClBwFwI](<https://www.youtube.com/watch?v=vbqKClBwFwI>)  
    [https://www.youtube.com/watch?v=f1605Zmwek8](<https://www.youtube.com/watch?v=f1605Zmwek8>)  
    [http://bitsavers.informatik.uni-stuttgart.de/pdf/xerox/alto/...](<http://bitsavers.informatik.uni-stuttgart.de/pdf/xerox/alto/Alto_Hardware_Manual_Aug76.pdf>)
  - nand2tetris를 몇 번 해봤지만, 모든 추상화 수준에서 단순함을 강조하기 때문에 **마이크로코드** 같은 것은 건너뜀  
    그 단순함 자체는 훌륭한 교훈이고 많은 영감을 줬지만, 1990년대 대학에서 들은 전기공학 수업은 nand2tetris와 비슷하게 8086류 CPU가 어떻게 만들어지는지 다루면서도 마이크로코드 동작을 설명했음  
    내부 프로그램 카운터가 제어 워드 테이블을 따라가고, 각 비트가 CPU의 제어 가능한 부분을 직접 조율하는 식이었음  
    각자 시뮬레이터에서 명령 하나를 구현했는데, 나는 DEC, 즉 감소 명령을 맡았음  
    어떤 의미에서는 nand2tetris의 명령어가 마이크로코드라고 볼 수도 있음  
    명령어 비트가 하드웨어를 직접 제어하고 첫 비트가 두 종류의 명령을 고르므로, 명령 하나당 코드 단계가 1개뿐임  
    반면 마이크로코드는 명령 하나가 임의 개수의 마이크로코드 단계를 가질 수 있음  
    Ben Eater의 브레드보드 8비트 CPU 영상에서는 명령어의 4비트 연산 코드와 단계 카운터로 ROM을 인덱싱해 제어 워드를 정함  
    이 ROM은 충분히 복잡한 논리 게이트로도 만들 수 있는 부분을 대신하며, 전자회로를 직접 만지고 문제를 해결해야 하므로 하드웨어 쪽 다음 단계로 좋음  
    다만 RAM이 16바이트뿐이라 nand2tetris처럼 더 높은 추상화 계층을 만들기 어렵다는 점은 아쉬움  
    그 시점에서는 더 나은 설계로 다시 만들거나 PCB에 올리거나, 6502 프로젝트로 넘어가 타이머, CPU, ROM, RAM, 입출력, UART 등을 하나로 묶어 생각한 뒤 이미 그런 것들이 합쳐진 마이크로컨트롤러로 넘어갈 수 있음  
    논리 게이트로 CPU를 만드는 방법을 읽고 싶다면 Charles Petzold의 Code는 느리게 설명하고 최근 개정됐으며, Danny Hillis의 Pattern on the Stone은 더 빠르게 진행됨  
    Code 2판은 4비트 사이클 카운터와 하드와이어드 논리 게이트로 각 사이클 동작을 정하고, 일부 논리에 다이오드 배열을 쓰는데 이것도 마이크로코드로 봐야 하는지 궁금함
  - nand2tetris가 **마이크로코드**를 다루거나 사용하는지 궁금함
