386处理器寄存器的异常复杂电路
摘要
对英特尔386处理器寄存器电路的详细逆向工程分析,揭示了六种不同的定制电路和交织位存储。
<p>开创性的英特尔386处理器(1985年)是x86架构中的第一款32位处理器。与大多数处理器一样,386包含众多寄存器;寄存器是处理器的关键组成部分,因为它们提供的存储速度远快于主内存。386的寄存器集包括通用寄存器、索引寄存器和段选择器,以及用于内存管理和操作系统实现的特殊功能寄存器。在这篇博文中,我将观察386的硅晶片,并解释处理器如何实现其主要寄存器。</p>
<p>事实证明,实现386寄存器的电路比预期的要复杂得多。在我研究的30个寄存器中,386并没有使用标准电路,而是使用了<em>六种</em>不同的电路,每种电路都针对寄存器的特定特性进行了优化。对于某些寄存器,英特尔将存储单元挤压在一起以加倍存储容量。其他寄存器支持一次访问8位、16位或32位。寄存器文件的大部分是“三端口”的,允许同时读取两个寄存器,同时将值写入第三个寄存器。最后,我惊讶地发现寄存器并非按顺序存储位:每个寄存器的低16位是交织的,而高16位则是线性存储的。</p>
<p>下面的照片显示了在特殊的金相显微镜下386的闪亮指甲大小的硅晶片。我标注了主要功能模块。对于本文来说,芯片左下象限的数据单元是相关组件。它由32位算术逻辑单元(ALU)以及处理器的主寄存器组(底部红色高亮部分)组成。这个称为数据通路的电路可以被视为处理器的核心。</p>
<p><a href="https://static.righto.com/images/386-regs2/386-die-labeled.jpg"><img alt="这张386的晶片照片显示了寄存器的位置。点击此图像(或任何其他图像)可查看大图。" class="hilite" height="534" src="https://static.righto.com/images/386-regs2/386-die-labeled-w500.jpg" title="这张386的晶片照片显示了寄存器的位置。点击此图像(或任何其他图像)可查看大图。" width="500" /></a><div class="cite">这张386的晶片照片显示了寄存器的位置。点击此图像(或任何其他图像)可查看大图。</div></p>
<p>数据通路采用规整的结构构建:每个寄存器或ALU功能单元都是一条水平电路带,形成了图像中可见的水平条纹。在大多数情况下,这个电路由32次复制的精心优化的电路组成,每次对应处理器的一个位。每个位的电路宽度完全相同——60微米——因此功能块可以像微型乐高积木一样堆叠在一起。为了连接这些电路,金属总线线路以32条为一组垂直穿过数据通路,允许数据在块之间上下流动。同时,控制线水平运行,使ALU操作或寄存器读写成为可能;数据单元右侧的不规则电路为这些控制线产生信号,为每条指令激活相应的控制线。</p>
<p>数据通路高度结构化,以最大化性能同时最小化其在晶片上的面积。下面,我将研究寄存器如何根据这种结构实现。</p>
<h2>386的寄存器</h2>
<p>处理器的寄存器是处理器架构最明显的特征之一。386处理器包含16个供应用程序员使用的寄存器,按现代标准数量很少,但在当时已经足够。下图显示了八个32位通用寄存器。顶部是四个名为EAX、EBX、ECX和EDX的寄存器。尽管这些寄存器是32位寄存器,但为了与早期处理器向后兼容,它们也可以被视为16位或8位寄存器。例如,EAX的低半部分可以作为16位寄存器AX访问,而EAX的低字节可以作为8位寄存器AL访问。此外,位15-8也可以作为8位寄存器AH访问。换句话说,访问EAX寄存器有四种不同的方式,其他三个寄存器也类似。正如我们将看到的,这些特性使寄存器集的实现复杂化。</p>
<p><a href="https://static.righto.com/images/386-regs2/gp-registers.jpg"><img alt="386中的通用寄存器。来自80386程序员参考手册,第2-8页。" class="hilite" height="317" src="https://static.righto.com/images/386-regs2/gp-registers-w350.jpg" title="386中的通用寄存器。来自80386程序员参考手册,第2-8页。" width="350" /></a><div class="cite">386中的通用寄存器。来自<a href="http://www.bitsavers.org/components/intel/80386/230985-001_80386_Programmers_Reference_Manual_1986.pdf#page=44">80386程序员参考手册</a>,第2-8页。</div></p>
<p>图的下半部分显示,32位EBP、ESI、EDI和ESP寄存器也可以被视为16位寄存器BP、SI、DI和SP。与之前的寄存器不同,这些寄存器不能被当作8位寄存器使用。386还有六个段寄存器,用于定义内存段的起始位置;这些是16位寄存器。16个应用寄存器还包括状态标志和指令指针(EIP);它们被视为32位寄存器,但其实现更为复杂。386还有大量用于操作系统编程的寄存器,但我在这里不讨论它们,因为它们可能位于芯片的其他部分。<span id="fnref:system-regs"><a class="ref" href="#fn:system-regs">1</a></span>最后,386有许多临时寄存器,这些寄存器对程序员不可见,但被微代码用于执行复杂指令。</p>
<h2>6T和8T静态RAM单元</h2>
<p>386的寄存器是用静态RAM单元实现的,这是一种可以保存一位的电路。这些单元排列成网格以提供多个寄存器。静态RAM可以与计算机用于主内存的动态RAM形成对比:动态RAM将每个位保存在一个微小的电容器中,而静态RAM则使用更快但更大且更复杂的电路。由于主内存保存数千兆字节的数据,它使用动态RAM来提供密集且廉价的存储。但寄存器的权衡不同:存储容量小,但速度至关重要。因此,寄存器使用我将在下面解释的静态RAM电路。</p>
<p>静态RAM单元背后的概念是将两个反相器连接成一个环路。如果一个反相器输入为“0”,它将输出“1”,反之亦然。因此,反相器环路将是稳定的,一个反相器打开,另一个关闭,每个反相器支持另一个。根据哪个反相器打开,电路存储0或1,如下所示。因此,这对反相器提供了一位内存。</p>
<p><a href="https://static.righto.com/images/386-regs2/inverter-loop.png"><img alt="环路中的两个反相器可以存储0或1。" class="hilite" height="121" src="https://static.righto.com/images/386-regs2/inverter-loop-w250.png" title="环路中的两个反相器可以存储0或1。" width="250" /></a><div class="cite">环路中的两个反相器可以存储0或1。</div></p>
<p>然而,为了有用,反相器环路需要一种方法将位存储到其中,以及一种读出存储位的方法。为了向电路中写入新值,输入两个信号,强制反相器达到所需的新值。一个反相器接收新的位值,而另一个反相器接收补码位值。这看起来像是一种强制更新位的方法,但它是有效的。诀窍在于单元中的反相器很小且很弱,而t</p>
查看缓存全文
缓存时间: 2026/05/16 03:34
# 386处理器寄存器那荒谬复杂的电路
来源:http://www.righto.com/2025/05/intel-386-register-circuitry.html
开创性的Intel 386处理器 \(1985\) 是x86架构中的首款32位处理器。与大多数处理器一样,386拥有众多寄存器;寄存器是处理器的关键部件,因为它们提供的存储速度远快于主内存。386的寄存器集包括通用寄存器、索引寄存器和段选择器,以及用于内存管理和操作系统实现的专用功能寄存器。在这篇博文中,我将观察386的硅晶圆,并解释处理器如何实现其主要寄存器。
结果发现,实现386寄存器的电路远比人们预期的复杂。在我研究的30个寄存器中,处理器没有使用标准电路,而是采用了*六*种不同的电路,每种电路都针对寄存器的特定特性进行了优化。对于某些寄存器,Intel将寄存器单元挤压在一起,使存储容量翻倍。其他寄存器支持一次访问8位、16位或32位。寄存器文件大部分是“三端口”的,允许同时读取两个寄存器,同时向第三个寄存器写入值。最后,我惊讶地发现,寄存器并不是按顺序存储位的:每个寄存器的低16位是交错的,而高16位是线性存储的。
下图是在特殊冶金显微镜下看到的386闪亮的指甲盖大小的硅晶圆。我标注了主要功能模块。对于本文,芯片左下象限的数据单元是相关组件。它由32位算术逻辑单元(ALU)以及处理器的主要寄存器组(底部以红色高亮显示)组成。这个称为数据通路的电路可以被视为处理器的心脏。
这张386晶圆照片显示了寄存器的位置。点击此图(或任何其他)可查看大图。(https://static.righto.com/images/386-regs2/386-die-labeled.jpg)
这张386晶圆照片显示了寄存器的位置。点击此图(或任何其他)可查看大图。
数据通路采用规则结构构建:每个寄存器或ALU功能单元都是一个水平的电路条纹,形成图中可见的水平带。在大多数情况下,该电路由精心优化的、重复32次的电路组成,每个电路对应处理器的一个位。每位电路宽度完全相同——60微米——因此功能模块可以像微观乐高积木一样堆叠在一起。为了连接这些电路,金属总线线垂直穿过数据通路,每32条一组,允许数据在模块之间上下流动。同时,控制线水平运行,实现ALU操作或寄存器读写;数据单元右侧的不规则电路为这些控制线生成信号,根据每条指令激活相应的控制线。
数据通路高度结构化,以在最大化性能的同时最小化其在晶圆上的面积。下面,我将研究寄存器如何按照这种结构实现。
处理器的寄存器是处理器架构最显著的特征之一。386处理器包含16个供应用程序程序员使用的寄存器,按现代标准看数量很少,但在当时已足够大。下图显示了八个32位通用寄存器。顶部是名为EAX、EBX、ECX和EDX的四个寄存器。虽然这些寄存器是32位的,但为了与早期处理器向后兼容,它们也可以被视为16位或8位寄存器。例如,EAX的低半部分可以作为16位寄存器AX访问,而EAX的低字节可以作为8位寄存器AL访问。此外,位15-8也可以作为称为AH的8位寄存器访问。换句话说,访问EAX寄存器有四种不同方式,其他三个寄存器也是如此。这些特性使寄存器组的实现变得复杂,稍后将会看到。
386中的通用寄存器。摘自80386程序员参考手册,第2-8页。(https://static.righto.com/images/386-regs2/gp-registers.jpg)
图的下半部分显示,32位的EBP、ESI、EDI和ESP寄存器也可以被视为16位寄存器BP、SI、DI和SP。与之前的寄存器不同,这些寄存器不能被视为8位寄存器。386还有六个段寄存器,用于定义内存段的起始位置;这些是16位寄存器。16个应用寄存器由状态标志和指令指针(EIP)补全;它们被视为32位寄存器,但其实现更为复杂。386还有大量用于操作系统编程的寄存器,但我不在这里讨论,因为它们很可能位于芯片的其他部分。1 (http://www.righto.com/2025/05/intel-386-register-circuitry.html#fn:system-regs) 最后,386有大量临时寄存器,这些对程序员不可见,但被微代码用于执行复杂指令。
## 6T和8T静态RAM单元
386的寄存器使用静态RAM单元实现,这是一种可以保存一位的电路。这些单元排列成网格以提供多个寄存器。静态RAM可以与计算机主内存使用的动态RAM形成对比:动态RAM将每个位保存在微型电容器中,而静态RAM使用更快但更大且更复杂的电路。由于主内存保存千兆字节的数据,它使用动态RAM来提供密集且廉价的存储。但寄存器的情况不同:存储容量很小,但速度至关重要。因此,寄存器使用我将在下面解释的静态RAM电路。
静态RAM单元背后的概念是将两个反相器连接成一个环路。如果反相器输入为“0”,则输出为“1”,反之亦然。因此,反相器环路将是稳定的,一个反相器打开,另一个关闭,并且相互支持。根据哪个反相器打开,电路存储0或1,如下图所示。因此,这对反相器提供了一位的存储。
两个反相器组成的环路可以存储0或1。(https://static.righto.com/images/386-regs2/inverter-loop.png)
两个反相器组成的环路可以存储0或1。
然而,为了让电路有用,反相器环路需要一种方法将位存储到其中,以及一种读出存储位的方法。要将新值写入电路,需要输入两个信号,强制反相器达到所需的新值。一个反相器接收新位值,另一个反相器接收互补位值。这似乎是用蛮力来更新位,但确实有效。诀窍在于单元中的反相器又小又弱,而输入信号电流更大,能够压倒反相器。2 (http://www.righto.com/2025/05/intel-386-register-circuitry.html#fn:flip) 这些信号通过称为“位线”的布线馈入;位线也可用于读取单元中存储的值。
通过向电路添加两个传输晶体管,可以读写单元。(https://static.righto.com/images/386-regs2/simple-cell.png)
通过向电路添加两个传输晶体管,可以读写单元。
为了控制对寄存器的访问,位线通过传输晶体管连接到反相器,这些晶体管充当开关,控制对反相器环路的访问。3 (http://www.righto.com/2025/05/intel-386-register-circuitry.html#fn:pass) 当传输晶体管导通时,写线上的信号可以通过并到达反相器。但当传输晶体管关断时,反相器与写线隔离。传输晶体管由一个控制信号开启,该信号称为“字线”,因为它控制对寄存器中一个存储字的访问。由于每个反相器由两个晶体管构成,上述电路由六个晶体管组成——因此这种电路被称为“6T”单元。
6T单元对读写使用相同的位线,因此不能同时读写寄存器。但是,添加两个晶体管可以创建一个“8T”电路,允许同时从一个寄存器读取并向另一个寄存器写入。(从技术上讲,寄存器文件是双端口的。)在下面的8T原理图中,两个额外的晶体管(G和H)用于读取。晶体管G缓冲单元的值;如果反相器输出为高电平,它会导通,将读取输出位线拉低。4 (http://www.righto.com/2025/05/intel-386-register-circuitry.html#fn:precharge) 晶体管H是一个传输晶体管,它在对该寄存器执行读取之前阻挡该信号;它由一个读取字线控制。注意,有两条用于写入的位线(和之前一样),以及一条用于读取的位线。
存储单元的原理图。每个晶体管用字母标记。(https://static.righto.com/images/386-regs2/cell-schematic.png)
存储单元的原理图。每个晶体管用字母标记。
为了构建寄存器(或内存),由这些单元构成一个网格。每一行对应一个寄存器,每一列对应一个位位置。水平线是字线,选择要访问的字,而垂直线是位线,将位传入或传出寄存器。对于写入,垂直位线提供32位(及其互补值)。对于读取,垂直位线从寄存器接收32位。激活一个字线以读写所选寄存器。总结:每一行是一个寄存器,数据垂直流动,控制信号水平流动。
静态存储器单元 (8T) 组织成网格。(https://static.righto.com/images/386-regs2/grid.png)
静态存储器单元 \(8T\) 组织成网格。
## 386中的六种寄存器电路
下面的晶圆照片放大了386处理器左下角的寄存器电路。你可以看到存储单元排列成网格,但注意图案在不同行之间会变化。该电路实现了30个寄存器:其中22个寄存器保存32位,而底部的寄存器是16位的。通过研究晶圆,我确定了六种不同的寄存器电路,我随意将其标记为(*a*)到(*f*)。在本节中,我将描述这六种寄存器。
386的主要寄存器组,位于数据通路的底部。数字表示可访问的寄存器位数。(https://static.righto.com/images/386-regs2/registers-labeled.jpg)
386的主要寄存器组,位于数据通路的底部。数字表示可访问的寄存器位数。
我从底部的简单电路开始:八个16位寄存器,我称其为(*f*)类型。你可以看到寄存器文件左侧有一个“凹口”,因为这些寄存器的宽度只有其他寄存器的一半(16位对32位)。这些寄存器采用前面描述的8T电路实现,因此是双端口的:可以在写入一个寄存器的同时读取另一个寄存器。如前所述,每个位有三条垂直总线穿过:一条用于读取的位线和两条用于写入的位线(极性相反)。每个寄存器有两条控制线(字线):一条用于选择要进行读取的寄存器,另一条用于选择要进行写入的寄存器。
下图显示了芯片上如何实现四个(*f*)类型单元。在此图像中,芯片的两个金属层以及大部分多晶硅布线已被去除,显示出底层的硅。深色轮廓表示掺杂硅区域,而掺杂区域上的条纹对应晶体管栅极。我用字母标记了每个晶体管,对应之前的原理图。观察到下半部分的布局是上半部分的镜像复制,这样可以节省一些空间。左右两侧大致镜像;不规则的形状允许独立的读写字线控制左右两半而不发生碰撞。
四个 (f) 类型存储器单元,用虚线分隔。小的不规则方块是未被完全去除的多晶硅残留。(https://static.righto.com/images/386-regs2/cell-f-labeled.jpg)
四个 \(*f*\) 类型存储器单元,用虚线分隔。小的不规则方块是未被完全去除的多晶硅残留。
386的寄存器文件和数据通路被设计为每位分配60微米的宽度。然而,上述寄存器的电路是不寻常的:上图宽度为60微米,但有两个寄存器单元并排放置。也就是说,该电路将*两个*位挤在60微米的宽度内,而不是一个。因此,这种密集布局每行实现两个寄存器(位交错排列),提供了其他寄存器电路两倍的密度。
如果你好奇上述晶体管是如何连接的,下面的原理图显示了上述晶体管的物理排列如何对应于前面描述的两个8T存储单元。由于386有两个重叠的金属层,解读带有金属层的晶圆照片非常困难。但如果你想看这些照片,请参考我之前的文章(https://www.righto.com/2023/11/reverse-engineering-intel-386.html)。
386中两个静态单元的原理图,标记为“R”和“L”代表“右”和“左”。原理图大致匹配物理布局。(https://static.righto.com/images/386-regs2/schematic-full.png)
386中两个静态单元的原理图,标记为“R”和“L”代表“右”和“左”。原理图大致匹配物理布局。
在(*f*)类型寄存器之上是10个(*e*)类型寄存器,占据五行单元。这些寄存器与之前一样是8T实现,但它们是32位宽而不是16位。因此,寄存器占据数据通路的整个宽度,与之前的寄存器不同。和之前一样,双密度电路每行实现两个寄存器。硅布局相同(除了是32位宽而不是16位),所以我不包含照片。
在这些寄存器之上是四个(*d*)寄存器,它们更复杂。它们是三端口寄存器,因此可以在写入一个寄存器的同时读取另外两个寄存器(例如,这对于ALU操作很有用,因为可以同时相加两个值并将结果写回)。为了支持读取第二个寄存器,每个位添加了另一条垂直总线。每个单元增加两个晶体管以将单元连接到新的位线。另一个字线控制额外的读取路径。由于每个单元多了两个晶体管,总共有10个晶体管,该电路称为10T。
四个 (d) 类型单元。条纹绿色区域是未被完全去除的氧化物层残留,可以忽略。(https://static.righto.com/images/386-regs2/cell-d-labeled.jpg)
四个 \(*d*\) 类型单元。条纹绿色区域是未被完全去除的氧化物层残留,可以忽略。
上图显示了四个(*d*)类型存储单元。每个单元占据完整的60微米宽度,与之前的双密度单元不同。这些单元在水平和垂直方向上镜像;这略微增加了密度,因为电源线可以在单元之间共享。我已经像之前一样标记了晶体管`A`到`H`,以及两个额外的晶体管`I`和`J`,用于第二条读取线。该电路是
相似文章
逆向工程386处理器的预取队列电路
详细介绍386处理器预取队列电路的逆向工程,解释所用的增量器、对齐网络和动态逻辑。
Intel 386标准单元逻辑中的异常电路
探索Intel 386标准单元逻辑中的异常电路,包括大型多路复用器和非标准反相器,突出芯片的设计历史和自动布局布线技术。
CT扫描仪揭示386处理器陶瓷封装内部的神奇结构
对英特尔386处理器陶瓷封装的CT扫描揭示了复杂的内部布线、多个电源网络和分层互连设计,为这款1985年芯片的封装技术提供了罕见的一瞥。
Intel 8087浮点芯片的指令解码
对Intel 8087浮点协处理器指令解码的详细逆向工程分析,解释主CPU与协处理器之间的交互、微码ROM的使用以及总线接口单元。
Intel 8087浮点芯片的堆栈电路逆向工程
本文详细介绍了对Intel 8087浮点协处理器堆栈电路的逆向工程,解释了该芯片基于堆栈的寄存器架构和微码ROM如何实现快速浮点运算。