寄存器 X/Y/ZMM16-31 是如何编码的?

问题描述

据我所知,从 AVX 开始,通过 3 字节 VEX 或 EVEX 前缀,您可以在 64 位模式下编码多达 32 个 XMM/YMM/ZMM 寄存器,但是当查看英特尔手册时告诉你这是可能的,我找不到它解释实际如何发生的部分。我只能看到一个扩展字段,即 REX 反转字段,但除了 EVEX 前缀中用于编码掩码寄存器的特殊位置之外,没有其他任何内容

您需要在某处使用 2 位来编码这么多寄存器。您是否必须以某种方式将 VEX/EVEX 前缀中的 2 个反向 REX 字段组合起来,或者这个过程是如何工作的?

解决方法

xmm16..31(以及它们的 ymm/zmm 等价物)是 AVX-512 的新特性,只能通过 EVEX 前缀访问,其中有 2 额外位要添加到每个 ModRM 字段,以及另外 5 位作为第三个操作数的额外字段。

REX + legacy-SSE,以及用于 AVX1/2 编码的 VEX,只能访问 xmm/ymm0..15。

Wikipedia's EVEX article 有一个很好的表格,显示了这些位的来源,我转录了其中的一些:

地址模式 第 4 位 第 3 位 位 [2:0] 注册类型
注册 EVEX.R' EVEX.R ModRM.reg 通用,矢量
RM EVEX.X EVEX.B ModRM.r/m 探地雷达,矢量
NDS/NDD EVEX.V' EVEX.v3 EVEX.v2v1v0 矢量
基础 0 EVEX.B SIB.base(或 modrm) 探地雷达
索引 0 EVEX.X SIB.index 探地雷达

如果 R/M 操作数是向量寄存器而不是内存寻址模式,则它同时使用 X(索引)和 B(基)位作为额外的寄存器编号位。因为这意味着没有 SIB.index 字段,它也可能需要扩展才能选择 r8..r15。


在 REX 和 VEX 前缀中,当源操作数不是具有索引寻址模式的内存时,X 位不再使用。 (https://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix,但请注意该页面前面的寄存器编号表中显示 X.RegX is just a placeholder for R or B,not REX.X;该页面上的选项令人困惑)。

另请参阅 x86 BSWAP instruction REX doesn't follow Intel specs? 以获取使用来自 REX 前缀的额外寄存器编号位的另一个图表。