Delphi XE/XE2 64位中的POPCNT

5

在Delphi XE或XE2下如何使用快速的Intel POPCNT指令计算16/32/64位字中1比特的数量?是否有一个库例程可以直接访问这个指令?能否有人编写一个演示汇编代码段来说明它的使用方法?最后,64位Delphi的选项是什么(无可用汇编)?


1
汇编语言在64位Delphi中也是可用的。 - Giel
我想这并不像在汇编块中写入 popcnt eax, eaxpopcnt rax, rcx 那么简单,是吗? - Rob Kennedy
1
略微偏离主题:http://www.strchr.com/crc32_popcnt 上有一个popcnt实现的比较表,其中一个使用SSSE3(通过半字节表查找的pshufb指令)的变体在某些系统上实际上能够击败popcnt。只有少数几个百分点,并不一定在所有CPU上都是相同的,并且只有在处理大量数据(100+字节)时才有益。非常快是相对的。 - FrankH.
@FrankH 我也测试了这个实现,因为我需要一个非常快的 popcount,但是我发现 SSSE3 版本比其他版本慢了近一个数量级,即使我使用大量数据。我怀疑某处存在错误或 bug。 - Gunther Piez
1个回答

2
如Rob Kennedy所建议的,这里提供了32位和64位Delphi IDE的函数。
function GetBitCount(num: integer): integer;
asm
  POPCNT    eax, num
end;

function GetBitCount(num: Int64): integer;
asm
  POPCNT    rax, num
end;

编辑: 这是32位和64位Delphi兼容版本

{$IF CompilerVersion < 23} //pre-XE2
  NativeInt = integer;
{$IFEND}

function GetBitCount(num: NativeInt): integer;
asm
{$IFNDEF CPUX64}
  POPCNT    eax, num
{$ELSE CPUX64}
  POPCNT    rax, num
{$ENDIF CPUX64}
end;

那最后一个看起来有点可疑,可能会在32位值上操作并存储在64位值中?要么将高32位清零,要么声明为int64类型? - Marco van de Voort
如果您使用变量 int size,则还需要在 popcnt 行中对寄存器进行 ifdef。 - Marco van de Voort
函数 GetBitCount(num: int64): int64; asm POPCNT rax, num end; - user1423467
抱歉: function GetBitCount(num: int64): int64; asm POPCNT rax, num end; 运行良好,但在测试中被 StrToInt() 捕获,因为它无法处理 64 位整数... 所以声明了 function StrToInt64( S: string): Int64; var E: integer; begin Val(S, Result, E); //if E <> 0 then ConvertErrorFmt(@SInvalidInteger, [S]); end; 它解决了问题 - 再次感谢所有人。 - user1423467
@user1423467:添加了32位和64位Delphi兼容版本。 - GJ.
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接