微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决寄存器是真的吗?它们在物理上是否存在于 CPU 中?

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

例如如果我这样做

mov       rax,60

这是否在硬件中找到了具有此指定名称的寄存器?

解决方法

CPU 硬件无法通过名称找到寄存器,而是由汇编程序将 rax 之类的名称转换为 3 位或 4 位寄存器数字 em> 在机器代码中。(寄存器名称所隐含的操作数大小也通过操作码和(缺少)前缀进行编码)。

例如add ecx,edx 组装到 01 d1Opcode 01 is add r/m32,r。第二个字节,ModRM 0xd1 = 0b0b11010001,对操作数进行编码:高 2 位 (11) 是寻址模式,普通寄存器,而不是内存(对于本例中的 dest,因为它是 01 add r/m32,r 而不是 { {1}})。
中间3位是03 add r32,r/m32字段,/r = 2是edx的寄存器号。
低3位为010字段,r/m为ECX的寄存器编号。
(编号为 EAX、ECX、EDX、EBX,...,可能是因为 8086 是 designed for asm source compatibility with 8080 - 即基于每条指令的“移植”足够简单,机器可以自动执行。)

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


对于 x86-64,寄存器编号始终为 4 位,但有时前导零是隐式的,例如在没有像 001 这样的 REX 前缀的指令中。寄存器编号位于该特殊编码的操作码的低 3 位。

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


如果是这样,我想知道为什么 x86_64 架构中只有 16 个寄存器......

为 x86 竞争的高性能用例设计的新 ISA很可能有 32 个整数寄存器。但是将其硬塞到 x86 机器代码中(就像 AVX-512 为矢量 regs 所做的那样),不值得花费代码大小的成本。

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

架构寄存器越多,每个操作数的机器码位就越多。更多的物理寄存器意味着更多的乱序执行能力来处理更多的寄存器重命名。 (物理寄存器编号是一个内部细节。)This article 测量实际的无序窗口大小以隐藏缓存未命中延迟,并将其与已知的 ROB 和 PRF 大小进行比较 - 在​​某些情况下 CPU 会耗尽物理寄存器在填充 ROB 之前,为所选的填充指令组合重命名。


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

更多架构寄存器通常确实有助于提高性能,但收益会递减。与 8 相比,16 避免了大量的存储/重新加载工作,但增加到 32 只会节省更多的存储/重新加载工作; 16 通常足以让编译器将他们想要的所有内容保存在寄存器中。

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

另见:

相关问答:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。