Assembly 使用rN寄存器(r8,r9,…)的程序集比其他寄存器具有更多的代码大小

Assembly 使用rN寄存器(r8,r9,…)的程序集比其他寄存器具有更多的代码大小,assembly,x86-64,machine-code,Assembly,X86 64,Machine Code,我有一个关于使用“rN”寄存器r8、r9、r10等的问题 我想用r8,r9,。。。在我的程序中注册了很多用法!但我发现代码大小有问题 比如说, mov eax, DWORD [rdi+4] 等于8b 47 04拆卸器 但是当我使用“rN”寄存器时,它是不同的 mov eax, DWORD [r9+4] 它等于41 8b 41 04它有一个额外的字节前缀 所以使用rN寄存器比使用其他寄存器有更多的代码大小!!!!!!!!!!!!!!!!!!!首先,为什么 第二,除了代码大小问题外,是否还有其他

我有一个关于使用“rN”寄存器r8、r9、r10等的问题

我想用r8,r9,。。。在我的程序中注册了很多用法!但我发现代码大小有问题

比如说,

mov eax, DWORD [rdi+4]
等于8b 47 04拆卸器

但是当我使用“rN”寄存器时,它是不同的

mov eax, DWORD [r9+4]
它等于41 8b 41 04它有一个额外的字节前缀

所以使用rN寄存器比使用其他寄存器有更多的代码大小!!!!!!!!!!!!!!!!!!!首先,为什么

第二,除了代码大小问题外,是否还有其他问题,如缓存、循环等。。。如果我们使用rN寄存器r8、r9、r10,。。。而不是其他寄存器

因此,使用rN寄存器比使用其他寄存器具有更多的代码大小

是的,这是一个众所周知的事实。REX前缀是x86-64机器代码与早期模式相比最重要的变化之一,这个问题只在性能方面值得回答,见下文

x86机器代码只有寄存器的3位字段。第四位(如果非零)需要来自REX前缀

这就是AMD64重新调整0x4用途的原因?32位机器码中的操作码字节是1字节inc/dec reg指令

为了让x86-64解码与16/32位模式解码在相同的晶体管上运行,AMD没有在前端需要一个全新的解码器块,而是选择了基本上不从头重新设计x86机器码。因此,它们只能使用3位寄存器字段,并且必须使用前缀字节

有关REX前缀的更多信息,请阅读英特尔第2卷手册。或者有一些有用的东西,包括比特含义的细节。它还解释说:

在以下情况下,必须对REX前缀进行编码:

使用64位操作数大小且指令不默认为64位操作数大小大多数指令默认为32位 操作数大小;或 使用扩展寄存器R8至R15、XMM8至XMM15、YMM8至YMM15、CR8至CR15和DR8至DR15中的一个;或 使用统一字节寄存器SPL、BPL、SIL或DIL之一。 使用AH、CH、BH或DH时不能使用。REX前缀,即使没有设置位,也会将AH的编码含义更改为SPL,以此类推

带有VEX前缀的指令(例如AVX和一些BMI/BMI2或EVEX AVX512)使用该前缀而不是REX作为额外寄存器位。2字节的VEX可以将X/YMM8..15编码为目标或第一个源,而无需使用更宽的3字节VEX前缀

第二,除了代码大小问题外,是否还有其他问题,如缓存、循环等。。。如果我们使用rN寄存器r8、r9、r10,。。。而不是其他寄存器

不,只是代码大小和某些CPU的前缀总数。带有uop缓存的CPU通常不会受到代码大小的直接影响,但间接影响(如较大的I-cache占用空间和uop缓存的不密集打包)仍然是一个问题。当然是大规模的,更大的二进制文件

但是,一些CPU(尤其是Silvermont系列)对带有3个以上前缀的指令的解码速度较慢,因此,例如,任何带有REX前缀的SSSE3/SSE4指令都会使解码器暂停。看见在Silvermont上,2字节操作码的0F操作码转义字节与SIMD指令编码的强制前缀一起被视为3字节之一

  401000:       66 0f 38 00 07          pshufb xmm0,XMMWORD PTR [rdi]   # 3 prefixes before the 00 opcode
  401005:       66 41 0f 38 00 00       pshufb xmm0,XMMWORD PTR [r8]    # 4 prefixes
后者在西尔弗蒙特的速度会特别慢。在其他具有3前缀限制的CPU上,尽管有些AMD IIRC;只有Silvermont系列将0F字节计为前缀


主流Intel CPU可以解码任意数量的前缀,而不会延迟,只受预解码阶段中每个时钟周期可查看的机器代码字节数的限制,预解码阶段查找指令之间的边界,以及主解码阶段,通过宏融合将多达5条或更多指令转换为多达5个UOP。Skylake其中之一的长度限制为每周期16字节;IIRC是预解码;如果需要,请查看Agner Fog的指南。

x86-64 ISA和新寄存器是x86-32 ISA的扩展,它构建在x86-16 ISA的基础上。随着更多指令和寄存器的添加,ISA无法满足所有要求,因此添加了特殊前缀,以告知下一条指令使用的是ISA的特定扩展,就像新的64位寄存器一样。字节41十六进制可能就是这样一个前缀字节。是的。。。我知道,正如我所说,这是“前缀”,但我想确定的缓存,周期。。。。。但是,有用的解释0x41是REX.B前缀,它用一个额外的位扩展指令中Mod R/M字节的RM字段,这是访问扩展寄存器所必需的。有关REX前缀字段的详细信息,请参阅《英特尔手册》中的第2.2.1.2节。您是否想知道,由于代码大小增加,使用这些寄存器时,性能是否会更差?我想可能是在某些情况下,代码的热段接近于溢出缓存线,但我不确定