0
4

4 回答 4

2

32 位系统不支持 64 位 POPCOUNT,因为

REX 前缀仅在长模式下可用。(不在 32 位操作系统中)

因此

写 POPCNTQ 会导致“popcnt 的指令后缀无效”。

见这里:http ://www.felixcloutier.com/x86/POPCNT.html (下面引用)

Opcode          Instruction         Op/En   64-Bit Mode  Compat/Leg Mode    Description
F3 0F B8 /r     POPCNT r16, r/m16   RM      Valid        Valid           POPCNT on r/m16
F3 0F B8 /r     POPCNT r32, r/m32   RM      Valid        Valid           POPCNT on r/m32
F3 REX.W 0F B8 /r POPCNT r64,r/m64  RM      Valid        N.E.            POPCNT on r/m64

一种解决方法是将 64/128 位拆分为两个/四个 32 位指令:

; a=uint_64, 64 bit operand, little endian
popcount eax, dword ptr [a]
popcount edx, dword ptr [a+4]
add eax, edx
xor edx, edx      ; for first mov below
mov dword ptr [b], edx      ; not neccessary, only due to 64 target op (will there ever be 2^64 bits set???)
mov dword ptr [b+4], eax

编辑:MASM32 代码中(二进制)HammingDistance 的 64 位操作数大小版本:

Hamming_64 PROC word1:QWORD , word2: QWORD
  mov ecx, dword ptr [word1]
  mov edx, dword ptr [word1+4]
  xor ecx, dword ptr [word2]
  xor edx, dword ptr [word2+4]
  popcnt eax, ecx 
  popcnt ebx, edx
  add eax, ebx   ; returns distance in EAX
  ret
Hamming_64 ENDP
于 2015-01-23T13:49:07.573 回答
2

popcnt是一个整数指令。因此,在 32 位模式下,您不能将其与 64 位操作数一起使用。您需要计算popcnt两半的 并将它们相加。这就是我测试过的所有 clang 版本为内置函数所做的。但是,我无法获得任何 gcc 版本来使用 popcnt 指令。因此,虽然通常建议使用内置函数,但在这种情况下,内联 asm 可能会更好。

于 2015-01-23T13:36:42.460 回答
1

我不知道是否有 32 位 popcnt 指令,但我敢打赌你不能在 32 位代码中使用 64 位 popcnt。尝试将 a 和 b 声明为 uint32_t。BTW uint64_t 是标准C, uint64 不是。

于 2015-01-23T13:16:19.640 回答
0

After implementing the 32 bits POPCNT using assembly, it looks like there is no real improvement compared to the SSSE3 shuffle assembly method. As I was suspecting, only the 64 bits POPCNT version can almost double the speed.

于 2015-01-25T21:16:00.603 回答