寄存器是真的吗?它们物理上存在于CPU中吗



我开始学习x86_64汇编,我注意到的一件事是使用寄存器,如rdi、rbp、rax、rbx。它们存在于CPU中吗?或者这是汇编程序使用的某种抽象机制吗?

例如,如果我做

mov       rax, 60

这能在硬件中找到指定名称的寄存器吗?

CPU硬件找不到名称的寄存器,这取决于汇编程序在机器代码中将rax等名称转换为3位或4位寄存器数字(寄存器名隐含的操作数大小也通过操作码和(缺少)前缀进行编码)。

例如add ecx, edx组装到01 d1。操作码01add r/m32, r。第二个字节ModRM0xd1 = 0b0b11010001对操作数进行编码:高2位(11)是寻址模式、普通寄存器,而不是内存(在这种情况下是dest,因为它是01 add r/m32, r而不是03 add r32, r/m32)
中间的3位是/r字段,010=2是edx的寄存器号
低3位为r/m字段,001为ECX的寄存器号
(编号为EAX、ECX、EDX、EBX…,可能是因为8086是为与8080兼容asm源代码而设计的,即在每个指令的基础上"移植"足够简单,机器可以自动完成。)

这就是CPU实际解码的内容;地址";其内部寄存器。一个没有寄存器重命名的简单有序CPU可以直接将这些数字用作实现寄存器文件的SRAM中的地址。(尤其是如果它是像MIPS或ARM这样的RISC。x86很复杂,因为你可以使用不同宽度的相同寄存器号,并且你有像AH和AL这样的部分寄存器映射到AX的一半。但是,如果你不进行寄存器重命名,这只是将寄存器号映射到SRAM中的位置的问题。)


对于x86-64,寄存器号总是4位,但有时前导零是隐式的,例如在没有REX前缀的指令(如mov eax, 60)中。寄存器号位于该特殊编码操作码的低3位。

在物理上,现代CPU使用物理寄存器堆和寄存器重命名表(RAT)来实现体系结构寄存器。因此,他们可以在多个时间点跟踪RAX的值。例如,mov eax, 60/push rax/mov eax, 12345/push rax可以并行运行两个mov指令,写入单独的物理寄存器。但仍在整理每个push应该从哪个中读取。


如果是这样的话,我想知道为什么x86_64体系结构中只有16个寄存器。。。

为x86与竞争的高性能用例设计的新ISA很可能有32个整数寄存器。但是把它硬塞进x86机器代码中(就像AVX-512对矢量regs所做的那样),不值得付出代码大小的代价。

x86-64由1979年设计的16位8086演变而来。在现代晶体管预算的情况下,如果现在重新开始,那么当时做出的许多设计选择都不是你会做的。(并非旨在实现与8位8080的asm源代码级兼容性)。

对于每个操作数,更多的体系结构寄存器在机器代码中花费更多的位。更多的物理寄存器只意味着更多的无序执行功能来处理更多的寄存器重命名。(物理寄存器编号是一个内部细节。)本文测量了用于隐藏缓存未命中延迟的实际无序窗口大小,并将其与已知的ROB和PRF大小进行了比较——在某些情况下,CPU在填充所选填充指令的ROB之前,已经用完了要重命名的物理寄存器。


,更多的寄存器不是意味着更高的性能吗?

更多的体系结构寄存器通常有助于提高性能,但回报递减。与8相比,16避免了大量的存储/重新加载工作,但增加到32只节省了更多的存储/再加载工作;对于编译器来说,16通常足以将它们想要的所有内容保存在寄存器中。

AMD设法将其扩展到16个寄存器(从8个增加到16个),这已经是一个显著的改进。是的,32个整数regs有时会更好一些,但如果不重新设计机器代码格式或使用更长的前缀(比如AVX-512的4字节EVEX前缀,它允许32个SIMD寄存器,对于AVX-512指令,x/y/zmm0..31),就无法实现

另请参阅:

  • 现代微处理器90分钟指南!

  • https://www.realworldtech.com/sandy-bridge/5/-Intel Sandybridge是Intel开始使用PRF(物理寄存器文件)而不是在ROB(重新排序缓冲区)中保留临时值的时候。

相关问答;As:

  • 现代处理器有多少EAX寄存器

最新更新