ถอดแอสเซมบลีไมโครโค้ดของ 80386 ได้แล้ว
(reenigne.org)- ROM ไมโครโค้ดของ 80386 มีขนาด 94,720 บิต ใหญ่กว่า 10,752 บิตของ 8086 มาก ทำให้การแปลงภาพและการตรวจสอบทำได้ยากกว่ามาก
- จากภาพไดความละเอียดสูง มีการผสาน การประมวลผลภาพ, โครงข่ายประสาทเทียม, และระบบอัตโนมัติที่มีมนุษย์ช่วยกำกับ เพื่อดึง binary blob ออกมาและตรวจสอบข้ามกันได้ภายในไม่กี่วัน
- ระหว่างกระบวนการถอดแอสเซมบลี โครงสร้างของอาร์เรย์ μ-op, ฟิลด์ บิต, รูปแบบการจบคำสั่ง, ตัวถอดรหัสคำสั่ง และโครงสร้าง PLA สำหรับ protection test ค่อย ๆ ถูกเปิดเผย
- 80386 มี ไมโครโค้ด สำหรับทุกคำสั่ง และหลายรูทีนมีหน้าที่ตั้งค่าฮาร์ดแวร์คูณ/หารและ barrel shifter มากกว่าจะเป็นอัลกอริทึมเอง
- พบความเป็นไปได้ของข้อบกพร่องในการจัดการ IO permission bitmap ใน protected mode โดยการเข้าถึงพอร์ต 4 ไบต์อาจตรวจสอบเพียง 3 แอดเดรสแรก แต่ยังไม่ได้ยืนยันแน่ชัด
การดึงและถอดแอสเซมบลีไมโครโค้ดของ 80386
- หลังจาก ถอดแอสเซมบลีไมโครโค้ดของ 8086 แล้ว Ken Shirriff ได้ให้ภาพความละเอียดสูงของ ROM ไมโครโค้ด ของ 80386 แต่ ROM ของ 80386 มีขนาด 94,720 บิต ใหญ่กว่า 10,752 บิตของ 8086 มาก จึงทำให้การแปลงและการตรวจสอบยากกว่ามาก
- 8086 มีสิทธิบัตรที่บอกทั้งโครงสร้างโดยรวมและชิ้นส่วนโค้ดบางส่วน จึงพอมีเบาะแสให้ค้นหา แต่ 80386 ใกล้เคียงกับการเป็น กล่องดำสมบูรณ์ มาก ทำให้หาว่าโครงสร้างซ่อนอยู่ตรงไหนในก้อนข้อมูลไบนารีขนาดใหญ่ได้ยาก
- ใน Discord มี GloriousCow, Smartest Blob และคนอื่น ๆ ทำงานต่อเพื่อดึงไมโครโค้ดจากภาพความละเอียดสูงของได 80386 โดยอุปสรรคหลักคือการเปลี่ยนจากภาพ → ไบนารี → ไมโครโค้ดที่มนุษย์เข้าใจได้
- มีการผสานการประมวลผลภาพ, โครงข่ายประสาทเทียม และระบบอัตโนมัติที่มีมนุษย์ช่วยกำกับ เพื่อดึง binary blob ออกจากภาพและตรวจสอบข้ามกันได้ภายในไม่กี่วัน
โครงสร้างที่เผยออกมาระหว่างการถอดแอสเซมบลี
- แม้จะดึงข้อมูลไบนารีออกมาได้แล้ว การถอดแอสเซมบลีก็ยังไม่ง่าย และต้องลองจับแพทเทิร์นหลายแบบก่อนจะเข้าใจวิธีจัดเรียงใหม่ให้แกนหนึ่งเป็น μ-op และอีกแกนเป็นบิตของ μ-op
- มีกลุ่ม μ-op ที่ไม่ได้ใช้งานอยู่ปลายด้านหนึ่ง ซึ่งกลายเป็นเบาะแสในการหาลำดับการอ่าน μ-op
- ในขั้นตอนการแบ่งบิตของ μ-op ออกเป็นหลาย ฟิลด์ มีการอาศัยประสบการณ์จากงานไมโครโค้ดของ 8086 เพื่อไล่หา source register field และ destination register field
- 80386 สามารถทำงาน ALU ได้ใน 2 ไซเคิล ดังนั้นเพื่อโหลดโอเปอแรนด์สองตัวเข้า ALU ในไซเคิลแรก และส่งผลลัพธ์ไปยังปลายทางในไซเคิลที่สอง จึงต้องมีฟิลด์สำหรับระบุอินพุตตัวที่สองของ ALU
- แพทเทิร์นที่ปรากฏซ้ำ ๆ ถูกคาดว่าเป็นตัวบอกการจบคำสั่ง และภายหลังก็ยืนยันได้ว่าถูกต้อง
- Ken มีส่วนช่วยโดยไล่ตามสายและบิตลอจิกหลายจุดบนไดของ 80386 เพื่อทำความเข้าใจวิธีเชื่อมต่อภายใน และโครงสร้างใหม่ที่ค้นพบก็กลายเป็นเบาะแสสำหรับตีความชิ้นส่วนไมโครโค้ดอื่นที่ใช้องค์ประกอบเดียวกัน
- นอกจากไมโครโค้ดแล้ว ยังมีการถอดรหัส ตัวถอดรหัสคำสั่ง ที่ประกอบด้วย PLA ขนาดเล็กหลายตัว และ PLA สำหรับ protection test ทำให้สามารถเชื่อมคำสั่งของ 386 เข้ากับชิ้นส่วนไมโครโค้ดได้
วิธีการทำงานของ 80386 ที่ต่างจาก 8086
- 80386 เร็วกว่า 8086 มากในคำสั่งส่วนใหญ่เมื่อวัดต่อไซเคิล และเพื่อให้ทำได้เช่นนั้นจึงใช้ทรานซิสเตอร์มากขึ้น
- อัลกอริทึมหลายอย่างที่ใน 8086 ทำด้วยไมโครโค้ด ถูกย้ายไปให้ ตัวเร่งฮาร์ดแวร์ รับหน้าที่ใน 80386
- ไมโครโค้ดของ 80386 จำนวนมากจึงไม่ได้ทำตัวอัลกอริทึมเอง แต่มีหน้าที่ตั้งค่าตัวเร่ง เช่น ฮาร์ดแวร์คูณ/หาร, barrel shifter และยูนิต protection test
- งานถอดแอสเซมบลีส่วนสำคัญจึงเป็นการทำความเข้าใจวิธีเชื่อมต่อระหว่าง อินเทอร์เฟซของตัวเร่ง เหล่านี้กับไมโครโค้ด
จุดเข้าไมโครโค้ดและการประมวลผลคำสั่ง
- จุดเข้า ของไมโครโค้ดจาก decoding ROM มี 215 จุด เพิ่มขึ้นมากจาก 60 จุดของ 8086
- จำนวนจุดเข้าที่เพิ่มขึ้นไม่ได้มาจากแค่การเพิ่มคำสั่งใหม่ แต่ยังเกิดจากการที่คำสั่งเดียวกันอาจต้องใช้รูทีนต่างกันตามว่าตัวโอเปอแรนด์เป็นรีจิสเตอร์หรือหน่วยความจำ, CPU อยู่ใน real mode หรือ protected mode, และมีการใช้คำนำหน้า REP หรือไม่
- รายการจุดเข้าทั้งหมดอยู่ในไฟล์
fields.txtพร้อมทั้ง subroutine และโค้ดที่ใช้ร่วมกัน - รูทีนไมโครโค้ดระดับบนหลายตัวทำงานเพียงเล็กน้อยก่อนกระโดดไปยังรูทีนที่แชร์กับจุดเข้าอื่น ๆ จึงยากจะเข้าใจความหมายจากขนาดของรูทีนระดับบนเพียงอย่างเดียว
- ตัวถอดรหัสคำสั่งไม่ได้ใช้แค่ opcode เพื่อตัดสินใจเลือกรูทีน ดังนั้นแม้แต่จำนวน opcode ที่แต่ละจุดเข้ารับผิดชอบก็อธิบายโครงสร้างได้ไม่ดีนัก
ทุกคำสั่งถูกประมวลผลด้วยไมโครโค้ด
- 80386 ต่างจาก 8086 หรือ CPU สมัยใหม่ตรงที่มันรัน μ-op อยู่เสมอ และมีไมโครโค้ดรองรับทุกคำสั่ง
- ยืนยันได้ว่าไม่มีคำสั่งใดที่ไม่ผ่านไมโครโค้ด
โค้ดที่ไม่ได้ใช้งานและร่องรอยของการจัดการข้อยกเว้น
- รูทีนตั้งแต่
0x849ถึง0x856ถูกทำเครื่องหมายเป็นunused?ในการถอดแอสเซมบลีไมโครโค้ด และดูเหมือนจะไม่มีจุดเข้าที่เชื่อมมาถึง - การทำงานที่แน่ชัดของรูทีนนี้ยังไม่ยืนยันทั้งหมด แต่มีจุดร่วมหลายอย่างกับรูทีน
#PF(PAGE_FAULT) ตั้งแต่0x8e9ถึง0x8f5 - ทั้งสองรูทีนจะตั้งค่ารหัสข้อผิดพลาดล่าสุดของ paging unit ก่อนจะไปต่อที่ interrupt 0x0e
- ความต่างคือรูทีนนี้ตั้งค่า
CR2ด้วยค่าที่ไม่ทราบความหมายจาก paging unit แทนที่จะเป็น fault linear address - ไมโครโค้ดที่เหลือดูเหมือนถูกออกแบบมาเพื่อทำพฤติกรรมตามที่ CPU ระบุไว้ในเอกสาร ส่วนรูทีนที่โต้ตอบกับฮาร์ดแวร์ ICE(In-Circuit Emulator) สำหรับดีบักระดับล่างนั้นเป็นพฤติกรรมที่ไม่ได้ถูกบันทึกในเอกสาร
ฟังก์ชันซ่อนอยู่และข้อบกพร่องที่เป็นไปได้ของ IO permission bitmap
- ยังไม่สามารถยืนยันได้เพราะยังไม่ได้ทดลองบนเครื่อง 386 จริง แต่มีความเป็นไปได้ว่าจะมีข้อบกพร่องในการจัดการ IO permission bitmap ที่บางระบบปฏิบัติการใน protected mode ใช้เพื่ออนุญาตให้โปรเซสใน user mode เข้าถึงพอร์ต IO ได้แบบจำกัด
- เมื่อเกิดการเข้าถึงพอร์ต 4 ไบต์ ไมโครโค้ดดูเหมือนจะตรวจสอบบิตสิทธิ์เพียง 3 แอดเดรสแรก
- หากโปรเซสทำการเข้าถึงลักษณะนี้ตรงขอบเขตของพื้นที่พอร์ต IO ที่ตนมีสิทธิ์ ไบต์สุดท้ายอาจผ่านได้อย่างผิดพลาดและทำให้ระบบปฏิบัติการไปแตะฮาร์ดแวร์รีจิสเตอร์ที่ไม่ได้ตั้งใจให้ผู้ใช้เข้าถึง
- บั๊กนี้เป็นกรณีเฉพาะมากจนถ้าไม่มีการถอดแอสเซมบลีไมโครโค้ดก็คงมองข้ามได้ แต่การพบช่องโหว่ด้านความปลอดภัยในฮาร์ดแวร์ที่ถูกใช้อย่างแพร่หลายมากว่า 40 ปีโดยไม่เคยถูกค้นพบมาก่อนก็ถือว่าไม่ธรรมดา
- พฤติกรรมนี้อาจมีอยู่เฉพาะใน CPU บางเวอร์ชัน หรืออาจเป็นไปได้ว่าการตีความรูทีนยังผิดและการทำงานจริงถูกต้องอยู่แล้ว
- ไมโครโค้ดนี้ดูเหมือนจะไม่ใช่ของ 80386 รุ่นแรก ๆ และคำสั่ง
XBTSกับIBTSไม่มีร่องรอยนอกจากในตัวถอดรหัส
แหล่งเรียนรู้และตำแหน่งดาวน์โหลด
- บทความอธิบายโครงสร้างภายในของ 80386 โดย nand2mario เป็นจุดเริ่มต้นที่ดีสำหรับการทำความเข้าใจงานถอดแอสเซมบลีนี้
- 80386 Multiplication and Division
- 80386 Barrel shifter
- 80386 Protection
- 80386 Memory Pipeline
- ผลการถอดแอสเซมบลีสามารถดาวน์โหลดได้จาก คลัง x86 microcode บน GitHub
parts.txtอธิบายหน้าที่ของไฟล์อื่น ๆ ส่วนmicrocode_10.txtคือไฟล์ที่เข้าไปดูตัวการถอดแอสเซมบลีไมโครโค้ดได้โดยตรง
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
สงสัยว่าพวกเขากู้คืน ไมโครโค้ด จาก ภาพไดความละเอียดสูง ได้อย่างไร
อยากรู้ว่ากระบวนการนี้เป็นการระบุทรานซิสเตอร์แต่ละตัวแล้วสร้างแบบจำลองวงจรหรือไม่ และผลลัพธ์ออกมาอยู่ในรูปแบบคล้าย Verilog หรือเปล่า
จากนั้นก็แยกประเภท 0 และ 1 โดย 1 สามารถแยกได้ด้วยสายตาจากการมีอยู่ของทรานซิสเตอร์และช่องว่างของโพลีซิลิคอน
ด้วยลักษณะของไมโครโค้ดของ Intel เราสามารถตั้งสมมติฐานได้ว่า 0 มีมากกว่าอย่างชัดเจน จึงถือว่าถ้ามีทรานซิสเตอร์ก็เป็น 1
มีเครื่องมือที่ทำอัตโนมัติด้วยค่า threshold ของสีเช่นกัน แต่บางส่วนของโมเสกเบลอและมีฝุ่นปนอยู่ ทำให้เกิด บิต 1 ปลอม จำนวนมาก จึงใช้งานได้ไม่ค่อยดี
สุดท้ายจึงฝึก convolutional neural network ให้จัดประเภทบริเวณบิตที่ดึงออกมาเป็น 0/1 แล้วตรวจผลโดยซ้อนสี่เหลี่ยมสีขาว/ดำแบบโปร่งใส 50% ทับบนโมเสกต้นฉบับ
หลังจากนั้นก็ใช้เวลาหลายวันตรวจแก้ข้อผิดพลาดแบบน่าเบื่อ จนสุดท้ายได้อาร์เรย์บิตดิบแบบ 2 มิติ และขั้นถัดไปคือการดึงคำไมโครโค้ดออกมาจากอาร์เรย์นั้น
https://youtu.be/HwEdqAb2l50?si=VFLed64PZvpCHfy1
“ภาพด้านบนแสดงส่วนหนึ่งของ ROM ไมโครโค้ด เมื่อดูผ่านกล้องจุลทรรศน์จะเห็นเนื้อหาของ ROM ไมโครโค้ด และอ่านบิตได้จากการมีหรือไม่มีทรานซิสเตอร์ในแต่ละตำแหน่ง”
https://www.righto.com/2020/06/a-look-at-die-of-8086-process...
เธรดที่เกี่ยวข้องซึ่งกำลังดำเนินอยู่: z386: An Open-Source 80386 Built Around Original Microcode - https://news.ycombinator.com/item?id=48248014 - พฤษภาคม 2026, 22 ความคิดเห็น
ตอนเช็กบล็อกของ reenigne เมื่อไม่กี่วันก่อนก็คิดว่า “อืม ไม่มีโพสต์หลังปี 2020 เลยแฮะ” เลยดีใจที่เขากลับมาโพสต์อีกครั้ง
และยิ่งน่าสนใจเป็นพิเศษที่บล็อกนี้ย้อนหลังไปได้ถึง 33 ปีก่อน
หนังสือดี ๆ ที่อธิบายการเขียนโปรแกรมระดับไมโครตั้งแต่พื้นฐาน: https://www.amazon.com/Computation-Structures-Optical-Electr...
หา PDF ฟรีได้ไม่ยากด้วย
ความพยายามที่ต้องใช้ในการทำ วิศวกรรมย้อนกลับ ไมโครโค้ดนี้น่าประทับใจมาก และนี่ก็เป็นบทความชั้นเยี่ยมที่เจาะลึกสถาปัตยกรรม 386
พอได้เห็น การติดตั้งใช้งานไมโครโค้ด จริง ๆ ก็ทำให้โปรเซสเซอร์เก่า ๆ ดูลึกลับน้อยลงว่าเคยจัดการการทำงานซับซ้อนได้อย่างไร
386 มีการเปลี่ยนแปลงเล็ก ๆ จำนวนมากตลอดช่วงการผลิต 22 ปี ดังนั้นจึงสำคัญที่จะรู้ว่าโค้ดนี้มาจาก รีวิชันของ 386 ตัวใด
9B5 BIST1 -> TMPD 0x0303 PASS29B6 SIGMA -> EDX9B7 BIST2 -> TMPE TMPD XOR9B8 SIGMA 0x3ddc0c2c XOR9B9 SIGMA -> EAX BOOTUP_JUMP JFPUOK0x303หมายถึง family 3, model 0, stepping ID 3งาน วิเคราะห์แบบกล่องดำ ที่ต้องใช้เพื่อถอดสิ่งนี้ออกมาช่างยากมหาศาล แต่ถ้าทำสำเร็จก็น่าจะสนุกมากและให้ความคุ้มค่ามากเช่นกัน
รู้สึกพอใจที่ครั้งหนึ่งเคยเรียนวิชายาก ๆ ในมหาวิทยาลัยเพื่อพยายามทำความเข้าใจบทความแบบนี้ และก็ชอบที่ HN ในปี 2015 ช่วยกระตุ้นวิธีคิดแบบนั้น
ทุกวันนี้แม้จะไม่ได้ใช้ความรู้การเขียนโปรแกรมระดับล่างมากนัก แต่ทุกครั้งที่ได้อ่านบทความแบบนี้ก็รู้สึกเหมือนสำนึกความคิดถูกเติมเต็มขึ้น เป็นความรู้สึกที่ยอดเยี่ยม
สำหรับคนที่เข้าถึงมหาวิทยาลัยได้ยาก ขอแนะนำ nand2tetris.org
การศึกษา RISC หรือ Transputer ซึ่งเป็นดีไซน์รุ่นเก่าที่เรียบง่ายกว่าก็ช่วยได้ และ 80386 อยู่คนละสุดของสเปกตรัมนั้น
เพราะมันซับซ้อนเกินจำเป็นจากการต้องคงดีไซน์เก่าที่ไม่ดีและความเข้ากันได้ย้อนหลังเอาไว้
การเรียนการออกแบบชิปไม่จำเป็นต้องเข้ามหาวิทยาลัยเสมอไป การดูบรรยายของ Alan Kay สักไม่กี่อัน หรือเปิดดูงานออกแบบคอมพิวเตอร์ใน Bitsavers ก็เป็นจุดเริ่มต้นที่ดีได้
ผมสร้าง Morphle Logic ซึ่งจำลองการออกแบบระดับเกตได้ง่ายกว่า FPGA และในปี 2026 สามารถแปลงไปเป็นทรานซิสเตอร์บนชิปได้ในราคาต่ำกว่า 200 ดอลลาร์
สุดท้ายมันอาจนำไปสู่การบูรณาการ ซูเปอร์คอมพิวเตอร์ระดับเวเฟอร์ ที่ใหญ่ขึ้น เร็วขึ้น และถูกลง
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/...
ความเรียบง่ายนั้นเองเป็นบทเรียนที่ยอดเยี่ยมและให้แรงบันดาลใจมาก แต่ในวิชาไฟฟ้าวิศวกรรมที่เรียนตอนมหาวิทยาลัยช่วงทศวรรษ 1990 ก็คล้าย nand2tetris ตรงที่อธิบายว่า CPU ตระกูล 8086 ถูกสร้างอย่างไร พร้อมกับอธิบายการทำงานของไมโครโค้ดด้วย
program counter ภายในจะไล่ตามตาราง control word และแต่ละบิตจะกำกับส่วนที่ควบคุมได้ของ CPU โดยตรง
ทุกคนต้องไปติดตั้งคำสั่งหนึ่งคำสั่งในซิมูเลเตอร์ของตัวเอง และผมได้รับคำสั่ง DEC หรือ decrement
ในแง่หนึ่ง คำสั่งของ nand2tetris ก็อาจมองได้ว่าเป็นไมโครโค้ด
เพราะบิตของคำสั่งควบคุมฮาร์ดแวร์โดยตรง และบิตแรกเลือกชนิดคำสั่งได้สองประเภท จึงมีเพียง 1 ขั้นโค้ดต่อ 1 คำสั่ง
ในทางกลับกัน ไมโครโค้ดสามารถมีจำนวนขั้นไมโครโค้ดต่อหนึ่งคำสั่งได้ตามต้องการ
ในวิดีโอ CPU 8 บิตแบบ breadboard ของ Ben Eater จะใช้ออปโค้ด 4 บิตของคำสั่งและตัวนับขั้นเพื่อทำดัชนีเข้า ROM แล้วกำหนด control word
ROM นี้ทำหน้าที่แทนส่วนที่สามารถสร้างได้ด้วยลอจิกเกตที่ซับซ้อนพอ และเพราะต้องลงมือแตะวงจรอิเล็กทรอนิกส์จริงและแก้ปัญหาด้วยตัวเอง จึงเป็นก้าวถัดไปที่ดีทางฝั่งฮาร์ดแวร์
เพียงแต่น่าเสียดายที่ RAM มีแค่ 16 ไบต์ ทำให้ยากจะสร้างชั้นนามธรรมที่สูงขึ้นแบบ nand2tetris
เมื่อถึงจุดนั้นก็อาจกลับไปทำใหม่ด้วยดีไซน์ที่ดีกว่า หรือย้ายลง PCB หรือขยับไปโปรเจกต์ 6502 เพื่อคิดรวมทั้ง timer, CPU, ROM, RAM, I/O, UART ฯลฯ ก่อนจะไปต่อยังไมโครคอนโทรลเลอร์ที่รวมสิ่งเหล่านั้นไว้แล้ว
ถ้าอยากอ่านเรื่องการสร้าง CPU จากลอจิกเกต หนังสือ Code ของ Charles Petzold อธิบายอย่างค่อยเป็นค่อยไปและเพิ่งมีฉบับปรับปรุงใหม่ ส่วน Pattern on the Stone ของ Danny Hillis ดำเนินเรื่องเร็วกว่า
Code ฉบับพิมพ์ครั้งที่ 2 ใช้ตัวนับรอบ 4 บิตและลอจิกเกตแบบ hardwired เพื่อกำหนดการทำงานของแต่ละรอบ และใช้ diode array ในบางส่วนของลอจิกด้วย ซึ่งทำให้สงสัยว่านั่นควรนับเป็นไมโครโค้ดหรือไม่