为什么 VPMOVMSKB 似乎产生了不正确的结果?

Why does VPMOVMSKB appear to produce incorrect results?

根据 Intel 文档,vpmovmskb 可以:

Instruction: vpmovmskb r32, ymm

Create mask from the most significant bit of each 8-bit element in a, and store the result in dst.

根据 GDB,我在 %ymm0 寄存器中有一个具有此值的向量: v32_int8 = {0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0}.

在我跨过指令 vpmovmskb %ymm0,%eax 之后,我希望得到一个 4 字节的位掩码,如下所示:0b00100000'10000010'00001000'00100000。但是根据 GDB,我在 %eax 中实际得到的是 0b00000100'00010000'01000001'00000100。我对此很困惑。看起来我期望的结果位移了 3,但我不知道为什么。

这里有人知道我可能遗漏了什么吗?我是否误解了正确的行为?

您观察到的不直观,但没有任何错误。 Visual Studio 调试器打印出同样的东西:

eax,b   0b00000100000100000100000100000100  unsigned int

当调试器打印 SIMD 向量时,它们会像存储在内存中一样打印它们。这意味着第一个通道在调试器的左侧。 Visual Studio 调试器是一个 GUI 应用程序,它显示可扩展数组,第一个元素在顶部,它还在元素附近显示从 0 开始的索引。

然而,当打印单个数字时,最低有效位在右边,最高有效位在左边。因此,当您查看以二进制形式打印的 uint32_t 数字时,您应该记住位顺序在那里是相反的:第一个位 #0 在字符串的右侧,最后一个位 #31 在字符串的左侧字符串。

在您的 AVX 向量中,设置高位的第一个字节位于通道 #2(假设 zero-based 编号),第二个字节位于通道 #8。如果您查看二进制结果,您会注意到右侧的位#2 和#8 设置为该数字。