不,您所说的寄存器是现代 x86 CPU 中不作为物理寄存器存在的实现细节。
x86 没有指定您在玩具/教学 CPU 设计中发现的任何实现细节。 x86 手册仅指定架构上可见的内容。
英特尔和 AMD 的优化手册详细介绍了内部实现,这与您的建议完全不同。现代 x86 CPU 将架构寄存器重命名为更大的物理寄存器文件,从而实现乱序执行,而不会因写后写或读后写数据危险而停止。 (有关寄存器重命名的更多详细信息,请参阅Why does mulss take only 3 cycles on Haswell, different from Agner's instruction tables?)。请参阅this answer 了解乱序执行的基本介绍,以及实际 Haswell 内核的框图。 (请记住,物理芯片有多个内核)。
与简单或玩具微架构不同,几乎所有高性能 CPU 都支持未命中和/或未命中命中(多个未完成的缓存未命中,而不是完全阻塞等待第一个完成的内存操作)
您可以构建一个具有单个 MBR / MDR 的简单 x86;如果最初的 8086 和 386 微架构有类似的东西作为内部实现的一部分,我不会感到惊讶。
但例如,Haswell 或 Skylake 内核每个周期可以从/到 L1d 缓存执行 2 次加载和 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 有 64 字节的 ZMM 加载/存储路径。 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,因为复杂的指令解码为超过 1 个内部 uop。)
现代 x86 以 16 或 32 字节的块为单位进行获取和解码,每个时钟周期最多解码 5 或 6 条指令,并将解码结果放入队列中,以便前端发出到无序部分核心。
另请参阅 https://stackoverflow.com/tags/x86/info 中的 CPU 内部链接,尤其是 David Kanter 的文章和 Agner Fog 的微架构指南。
顺便说一句,您遗漏了 x86 的许多控制/调试寄存器。 CR0..4 对于 386 启用保护模式、分页和各种其他内容至关重要。您可以仅使用 GP 和段 reg 以及 EFLAGS 在实模式下使用 CPU,但如果您包含操作系统需要管理的非通用 reg,x86 具有更多的体系结构寄存器。