1 puntos por GN⁺ 2 시간 전 | 1 comentarios | Compartir por WhatsApp
  • La ROM de microcódigo del 80386 tiene 94,720 bits, muchísimo más que los 10,752 bits del 8086, lo que hizo mucho más difícil la conversión de imagen y la verificación
  • A partir de imágenes del die en alta resolución, se extrajo y validó de forma cruzada un blob binario en pocos días combinando procesamiento de imagen, redes neuronales y automatización asistida por personas
  • Durante el proceso de desensamblado fueron apareciendo gradualmente la disposición de μ-op, los campos de bits, los patrones de finalización de instrucciones, el decodificador de instrucciones y la estructura de la PLA de pruebas de protección
  • El 80386 tiene microcódigo para todas las instrucciones, y muchas rutinas se encargan más de configurar el hardware de multiplicación/división y el barrel shifter que de implementar algoritmos
  • Se detectó un posible defecto en el manejo del bitmap de permisos de IO en modo protegido: en accesos a puertos de 4 bytes, parecería revisar solo las primeras 3 direcciones, aunque todavía no está confirmado

Extracción y desensamblado del microcódigo del 80386

  • Después de desensamblar el microcódigo del 8086, Ken Shirriff proporcionó imágenes en alta resolución de la ROM de microcódigo del 80386, pero la ROM del 80386, con 94,720 bits, es muchísimo más grande que la del 8086, con 10,752 bits, así que convertirla y verificarla fue bastante más difícil
  • El 8086 tenía una patente con la estructura general y algunos fragmentos de código, lo que daba pistas de búsqueda, pero el 80386 era prácticamente una caja negra completa, así que era difícil encontrar estructura dentro de un gran bloque binario
  • En Discord, GloriousCow, Smartest Blob y otros continuaron el trabajo de extraer el microcódigo a partir de imágenes en alta resolución del die del 80386, y el principal obstáculo fue transformar imagen → binario → microcódigo comprensible
  • Combinando procesamiento de imagen, redes neuronales y automatización asistida por personas, lograron extraer de la imagen un blob binario y validarlo de forma cruzada en cuestión de días

Estructuras reveladas durante el proceso de desensamblado

  • Incluso después de extraer el binario, desensamblarlo no fue sencillo, y al ir ajustando distintos patrones se descubrió cómo reordenarlo para que en un eje quedaran las μ-op y en el otro los bits de μ-op
  • Había un bloque de μ-op no usado en uno de los extremos, lo que sirvió como pista para determinar el orden en que se leen las μ-op
  • En el proceso de dividir los bits de μ-op en varios campos, se fueron identificando los campos de registro fuente y registro destino basándose en la experiencia previa del trabajo con el microcódigo del 8086
  • Como el 80386 puede realizar operaciones ALU en 2 ciclos, hacía falta un campo que especificara la segunda entrada de la ALU para cargar los dos operandos en el primer ciclo y enviar el resultado al destino en el segundo
  • Se supuso que los patrones repetidos marcaban el final de una instrucción, y después se confirmó que efectivamente era así
  • Ken contribuyó rastreando múltiples líneas y bits lógicos del die del 80386 para entender cómo estaban conectados internamente, y cada nueva estructura revelada daba pistas para interpretar otros fragmentos de microcódigo que usaban la misma construcción
  • Junto con el microcódigo, también se descifraron el decodificador de instrucciones, compuesto por varias PLA pequeñas, y la PLA de pruebas de protección, lo que permitió vincular las instrucciones del 386 con fragmentos de microcódigo

Cómo ejecuta el 80386, a diferencia del 8086

  • El 80386 es mucho más rápido por ciclo que el 8086 en la mayoría de las instrucciones, y para lograrlo usa más transistores
  • Varios algoritmos que en el 8086 estaban implementados en microcódigo pasan en el 80386 a manos de algo que en la práctica funciona como un acelerador de hardware
  • Buena parte del microcódigo del 80386 no implementa tanto el algoritmo en sí, sino que se encarga de configurar aceleradores como el hardware de multiplicación/división, el barrel shifter y la unidad de pruebas de protección
  • Una gran parte del trabajo de desensamblado consistió en averiguar cómo se conectan estas interfaces de aceleradores con el microcódigo

Puntos de entrada del microcódigo y procesamiento de instrucciones

  • Hay 215 puntos de entrada de microcódigo desde la ROM de decodificación, un aumento importante frente a los 60 del 8086
  • El aumento no se debe solo a nuevas instrucciones, sino también a que una misma instrucción puede procesarse con rutinas distintas según si el operando está en registro o memoria, si la CPU está en modo real o modo protegido, o si se está usando el prefijo REP
  • La lista completa de entradas está en el archivo fields.txt, junto con subrutinas y código compartido
  • Muchas rutinas de microcódigo de alto nivel hacen muy poco antes de saltar a rutinas compartidas con otros puntos de entrada, así que el tamaño de la rutina superior por sí solo no basta para entender su propósito
  • Como el decodificador de instrucciones no decide qué rutina usar solo a partir del opcode, tampoco es fácil describir la estructura únicamente por la cantidad de opcodes que maneja cada punto de entrada

Todas las instrucciones se manejan con microcódigo

  • A diferencia del 8086 o de CPUs modernas, el 80386 siempre ejecuta μ-op, y existe microcódigo correspondiente para todas las instrucciones
  • Se confirmó que no hay instrucciones que se ejecuten sin pasar por microcódigo

Rastros de código no usado y manejo de excepciones

  • Las rutinas entre 0x849 y 0x856 aparecen marcadas como unused? en el desensamblado del microcódigo, y parece que no tienen puntos de entrada conectados
  • Su funcionamiento exacto no está totalmente claro, pero tienen muchas similitudes con la rutina #PF(PAGE_FAULT) entre 0x8e9 y 0x8f5
  • En ambos casos, la rutina termina configurando el último código de error de la unidad de paginación y luego continúa hacia la interrupt 0x0e
  • La diferencia es que esta rutina parece cargar en CR2 un valor desconocido proveniente de la unidad de paginación, en lugar de la fault linear address
  • El resto del microcódigo parece estar diseñado para implementar el comportamiento documentado de la CPU, mientras que las rutinas que interactúan con hardware de ICE (In-Circuit Emulator) para depuración de bajo nivel corresponden a comportamiento no documentado

Funciones ocultas y posible fallo en el bitmap de permisos de IO

  • Aunque todavía no pudo confirmarse con pruebas en una máquina 386 real, podría haber un problema en el manejo del bitmap de permisos de IO, usado por algunos sistemas operativos en modo protegido para permitir acceso limitado a puertos de IO desde procesos en modo usuario
  • Cuando ocurre un acceso a puerto de 4 bytes, el microcódigo parece revisar solo los bits de permiso de las primeras 3 direcciones
  • Si un proceso hace ese acceso justo en el límite de una región de puertos de IO para la que sí tiene permisos, el acceso al último byte podría completarse incorrectamente y alcanzar un registro de hardware al que el sistema operativo no pretendía dar acceso al usuario
  • Es un caso muy específico y podría haber pasado desapercibido sin este desensamblado del microcódigo, pero sigue siendo inusual que un fallo de seguridad en hardware tan usado durante más de 40 años no haya sido detectado
  • También es posible que ese comportamiento solo exista en algunas versiones del CPU, o que la interpretación de la rutina sea incorrecta y en realidad funcione bien
  • Este microcódigo no parece corresponder a una versión temprana del 80386, y las instrucciones XBTS e IBTS no dejan rastro salvo en el decodificador

Material de estudio y dónde descargarlo

1 comentarios

 
GN⁺ 2 시간 전
Comentarios en Hacker News
  • Me pregunto cómo se puede reconstruir el microcódigo a partir de una imagen del die de alta resolución
    También quisiera saber si el proceso consiste en identificar cada transistor para modelar el circuito, y si el resultado termina en una forma como Verilog

    • Participé un poco en el proceso de extracción: primero se marcaron las coordenadas x,y de todos los bits tomando como referencia los puntos donde se cruzan las filas y columnas del arreglo de microcódigo
      Después se clasificaron los 0 y los 1; los 1 podían distinguirse visualmente por la presencia de transistores y por el hueco en el polisilicio
      Por las características del microcódigo de Intel, se podía asumir que había muchos más 0 que 1, así que si había un transistor se tomaba como un 1
      Existen herramientas para automatizar esto con umbrales de color, pero como partes del mosaico estaban borrosas y había polvo, aparecían muchos bits 1 falsos, así que no funcionó bien
      En su lugar, se entrenó una red neuronal convolucional para clasificar en 0/1 las regiones extraídas de bits, y se verificó el resultado superponiendo rectángulos blancos o negros con 50% de opacidad sobre el mosaico original
      Después vinieron varios días de revisar errores de forma tediosa, y al final se obtuvo el arreglo crudo bidimensional de bits; el siguiente paso es extraer de ese arreglo las palabras de microcódigo
    • Hay un video donde van retirando capa por capa el chip del mecanismo de bloqueo de Nintendo 64, y trata este tipo de trabajo con bastante profundidad desde varios ángulos
      https://youtu.be/HwEdqAb2l50?si=VFLed64PZvpCHfy1
    • Basta con ver la imagen en sí
      “La foto de arriba muestra parte de la ROM de microcódigo. Bajo el microscopio se puede ver el contenido de la ROM de microcódigo, y se pueden leer los bits según haya o no un transistor en cada posición”
      https://www.righto.com/2020/06/a-look-at-die-of-8086-process...
    • El microcódigo está en una ROM, y tiene una estructura regular en la que los 1 y los 0 se ven distintos
  • Hilo relacionado en curso: z386: An Open-Source 80386 Built Around Original Microcode - https://news.ycombinator.com/item?id=48248014 - mayo de 2026, 22 comentarios

  • Cuando revisé el blog de reenigne hace unos días pensé “hmm, no hay entradas desde 2020”, así que da gusto verlo de vuelta
    También es especialmente curioso que el blog se remonte hasta hace 33 años

    • Puede que ver subir el contador de visitas haya sido lo que lo motivó a escribir
  • Un buen libro que explica la microprogramación desde cero: https://www.amazon.com/Computation-Structures-Optical-Electr...
    También es fácil encontrar un PDF gratis

  • Impresiona el esfuerzo necesario para hacer ingeniería inversa de este microcódigo, y es un gran artículo que profundiza mucho en la arquitectura del 386

  • Ver la implementación del microcódigo en la práctica hace que resulte menos misterioso cómo los procesadores antiguos manejaban operaciones complejas

  • El 386 tuvo muchos cambios pequeños durante sus 22 años de producción, así que es importante saber de qué revisión del 386 salió este código

    • Una pista es el valor que se carga en EDX al hacer 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 significa familia 3, modelo 0, stepping ID 3
  • El análisis de caja negra necesario para descifrar esto es increíblemente difícil, pero si sale bien debe de ser muy divertido y también muy satisfactorio

  • Me da gusto haber llevado materias difíciles en la universidad para poder entender textos como este, y también que HN en 2015 incentivara ese tipo de pensamiento
    Aunque hoy ya no use mucho conocimiento de programación de bajo nivel, cada vez que leo algo así siento que me enriquece la conciencia, y eso está genial
    Para quien no tenga fácil acceso a la universidad, recomiendo nand2tetris.org

    • Construir tú mismo un microprocesador desde las compuertas es una forma más sencilla de entender el diseño de microcódigo y el funcionamiento de un procesador
      También ayuda estudiar diseños antiguos y simples como RISC o el Transputer, y el 80386 está en el extremo opuesto de ese espectro
      Se volvió innecesariamente complejo por intentar mantener compatibilidad con diseños viejos y malos
      No es indispensable la universidad para aprender diseño de chips; también es un buen punto de partida ver algunas conferencias de Alan Kay o revisar materiales de diseño de computadoras en Bitsavers
      Hice Morphle Logic para simular diseño a nivel de compuertas de una forma más fácil que con FPGA y convertirlo en transistores sobre chip por menos de 200 dólares a valores de 2026
      Al final eso podría llevar a integraciones cada vez más grandes, rápidas y baratas de supercomputadoras a escala de oblea
      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/...
    • He hecho nand2tetris varias veces, pero como enfatiza la simplicidad en todos los niveles de abstracción, se salta cosas como el microcódigo
      Esa simplicidad en sí misma es una gran lección y me dio mucha inspiración, pero las clases de ingeniería eléctrica que tomé en la universidad en los 90 eran parecidas a nand2tetris y además explicaban cómo se construía una CPU tipo 8086, incluyendo cómo funcionaba el microcódigo
      Había un contador de programa interno que seguía una tabla de palabras de control, y cada bit coordinaba directamente una parte controlable de la CPU
      Cada quien implementó una instrucción en su simulador; a mí me tocó DEC, es decir, la instrucción de decremento
      En cierto sentido, podría decirse que las instrucciones de nand2tetris son microcódigo
      Los bits de instrucción controlan directamente el hardware y el primer bit elige entre dos tipos de instrucciones, así que cada instrucción tiene solo una etapa de código
      En cambio, con microcódigo una instrucción puede tener una cantidad arbitraria de etapas de microcódigo
      En los videos de la CPU de 8 bits en protoboard de Ben Eater, la palabra de control se determina indexando una ROM con el opcode de 4 bits de la instrucción y el contador de etapas
      Esa ROM reemplaza una parte que también podría construirse con compuertas lógicas lo bastante complejas, y como hay que manipular directamente los circuitos electrónicos y resolver problemas, es un buen siguiente paso del lado de hardware
      Eso sí, da lástima que solo tenga 16 bytes de RAM, porque eso dificulta construir capas de abstracción más altas como en nand2tetris
      En ese punto, se puede rehacer con un mejor diseño, montarlo sobre una PCB, o pasar a un proyecto con 6502 para pensar en conjunto en temporizadores, CPU, ROM, RAM, entrada/salida, UART, etc., y luego pasar a microcontroladores donde todo eso ya viene integrado
      Si quieres leer sobre cómo construir una CPU con compuertas lógicas, Code de Charles Petzold lo explica con calma y fue actualizado recientemente, mientras que The Pattern on the Stone de Danny Hillis avanza más rápido
      La segunda edición de Code usa un contador cíclico de 4 bits y compuertas lógicas cableadas para definir lo que ocurre en cada ciclo, y en parte de la lógica usa arreglos de diodos; me pregunto si eso también debería considerarse microcódigo
    • Me pregunto si nand2tetris trata o usa microcódigo