x86寄存器:MBR / MDR和指令寄存器

时间:2018-07-25 15:13:24

标签: x86 cpu cpu-architecture cpu-registers

据我了解,IA-32体系结构具有10个32位和6个16位寄存器。

32位寄存器如下:

  • 数据寄存器-EAX,EBX,ECX,EDX
  • 指针寄存器-EIP,ESP,EBP
  • 索引寄存器-ESI,EDI
  • 控制寄存器-EFLAG(EIP也归类为控制寄存器)

16位寄存器如下:

  • 代码段:包含所有要执行的指令。
  • 数据段:它包含数据,常量和工作区。
  • 堆栈段:它包含数据或过程或子例程的返回地址。
  • 附加段(ES)。指向额外数据的指针。
  • F段(FS)。指向更多额外数据的指针。
  • G段(GS)。指向更多额外数据的指针。

但是,我在当前指令寄存器(CIR)或内存缓冲寄存器(MBR)/内存数据寄存器(MBR)上找不到任何信息。这些寄存器是否被称为别的东西?这些寄存器是32位的吗?

我假设它们是32位的,并且该体系结构下最常用的指令的长度不足4个字节。从观察来看,许多指令似乎不足4个字节,例如:

  • 推压EBP(55)
  • MOV EBP,ESP(8B EC)
  • LEA(8D 44 38 02)

对于更长的指令,CPU将使用前缀代码和其他可选代码。较长的指令需要一个以上的周期才能完成,这取决于指令的长度。

我是否要纠正,因为所涉及的寄存器长度为32位?在IA-32架构中还有其他我应该注意的寄存器吗?

1 个答案:

答案 0 :(得分:5)

不,您要谈论的寄存器是一种实现细节,在现代x86 CPU中不作为物理寄存器存在。

x86没有指定您在玩具/教学CPU设计中发现的所有实现细节。 x86手册仅指定在结构上可见的内容。

英特尔和AMD的优化手册详细介绍了内部实现,这与您的建议完全不同。现代x86 CPU将体系结构寄存器重命名为更大的物理寄存器文件,从而可以无序执行而不会因写后写或读后写数据危险而停顿。 (有关寄存器重命名的更多详细信息,请参见Why does mulss take only 3 cycles on Haswell, different from Agner's instruction tables?)。有关乱序执行的基本介绍和实际的Haswell内核的框图,请参见this answer。 (请记住,一个物理芯片具有多个核心。)


与简单或玩具式微体系结构不同,几乎所有高性能CPU都支持未命中和/或未命中(多个未完成的高速缓存未命中,并不完全阻塞等待第一个完成的内存操作)


可以构建一个具有单个MBR / MDR的简单x86;如果原始的8086和386微体系结构在内部实现中具有类似的功能,我不会感到惊讶。

但是,例如,Haswell或Skylake内核每个周期可以进行L1d高速缓存的加载和1次存储(请参见How can cache be that fast?)。显然,他们不能只有一个MBR。相反, Haswell拥有72个加载缓冲区条目和42个存储缓冲区条目,它们都是内存顺序缓冲区的一部分,它们支持乱序执行加载/存储,同时保持以下错觉:仅StoreLoad重新排序发生/对其他内核可见。

自P5 Pentium naturally-aligned loads/stores up to 64 bits are guaranteed atomic起,但在此之前只有32位访问权限是原子访问。所以是的,如果386/486具有MDR,则它可能是32位。但是,即使是那些早期的CPU也可能在CPU和RAM之间缓存。

我们知道Haswell and later have a 256-bit path between L1d cache and execution units(即32个字节)和Skylake-AVX512具有用于ZMM加载/存储的64字节路径。 AMD CPU将矢量操作分成128位块,因此它们的加载/存储缓冲区条目大概只有16个字节宽。

Intel CPU至少将相邻的存储合并到存储缓冲区中的同一高速缓存行中,并且还有10个LFB(行填充缓冲区)用于L1d和L2(或从内核到L3或DRAM)之间的挂起传输


指令解码:x86是可变长度的

x86是可变长度指令集;在前缀之后,最长的指令长于32位。即使对于8086,也是如此。例如,add word [bx+disp16], imm16为6个字节长。但是8088只有一个4字节的预取队列可以进行解码(与8086的6字节队列相比),因此它必须支持解码指令,而无需从内存中加载整个内容。 8088/8086解码的前缀每次循环1个周期,而4个字节的操作码+ modRM绝对足以识别其余指令的长度,因此它可以对其进行解码,然后如果没有,则获取disp16和/或imm16。还没有。现代的x86可以具有更长的指令,尤其是在SSSE3 / SSE4需要操作码中包含许多强制性前缀的情况下。

它也是CISC ISA,因此在内部保留实际的指令字节不是很有用。您不能像使用简单的MIPS那样直接将指令位用作内部控制信号。

在非流水线CPU中,是的,某处可能只有一个物理EIP寄存器。对于现代CPU,每条指令都具有与其关联的EIP,但是许多指令在CPU内部立即运行。有序的流水线CPU可能会将EIP与每个阶段相关联,但无序的CPU将必须在每个指令的基础上对其进行跟踪。 (实际上是每个uop,因为复杂的指令会解码为多个内部uop。)

现代x86以16或32字节的块为单位进行获取和解码,每个时钟周期最多解码5或6条指令,并将解码结果放入队列中,以使前端发出到队列中乱码部分核心。

另请参见https://stackoverflow.com/tags/x86/info中的CPU内部链接,特别是David Kanter的文章和Agner Fog的微体系结构指南。


顺便说一句,您省略了x86的许多控制/调试寄存器。 CR0..4对于386启用保护模式,分页和其他各种功能至关重要。您只能使用GP和段寄存器以及EFLAGS在实模式下使用CPU,但是如果您包含操作系统需要管理的非通用寄存器,则x86的体系结构寄存器要多得多。