我对白皮书“使用 PCLMULQDQ 指令对通用多项式进行快速 CRC 计算”中如何计算位反射常数感到困惑。
在帖子使用 PCLMULQDQ 的快速 CRC NOT 反映 和当我们在 CRC32 中使用 CLMUL 时如何计算位反射常数中,@rcgldr 提到“...进行调整以补偿偏移,因此而不是 x^(a) mod poly,它是 (x^(a-32) mod poly)<<32...”,但我不明白这是什么意思。
例如,常数 k1=(x^(4*128+64)%P(x))=0x8833794c (第 16 页) k1'=(x^(4*128+64-32)%P(x)<<32)'=(0x154442db4>>1)(第22页),我看不出这两个数字有任何反射关系(10001000_00110011_01111001_01001100 v.s 10101010_00100010_00010110_11011010)。
我想我的问题是为什么指数需要减去32来补偿32位左移?为什么 k1 和 (k1)' 没有反映?
您能帮忙解释一下吗?谢谢
我在网上,特别是在StackOverflow上仔细搜索了这个问题的答案,我试图理解相关帖子,但需要一些专家来解释更多。
我修改了最初的一些 Intel 示例以与 Visual Studio 配合使用 | Windows,未反映和反映了 16、32 和 64 位 CRC,在此 github 存储库中。
https://github.com/jeffareid/crc
我添加了一些缺失的注释,还添加了一个程序来生成 6 种情况中每种情况的汇编代码中使用的常量。
不是 x^(a) mod poly,而是 (x^(a-32) mod poly)<<32
这是针对非反射 CRC 进行的。 CRC 以及常数保留在高 32 位中,因此 PCLMULQDQ 的结果最终位于高 64 位中,然后右移。将常量左移 32 位与乘以 2^32 或多项式表示法 x^32 相同。
对于反射 CRC,CRC 保留在低 32 位中,逻辑上它们是反射数的高 32 位。问题是 PCLMULQDQ 将乘积乘以 2,将乘积右移 1 位,留下位 127 == 0 以及位 126 到 0 中的 127 位乘积。为了补偿这一点,常数为 (x^(a) mod聚) << 1 (left shift for reflected number is == divide by 2).
该 github 站点上的示例代码包括 crc32rg.cpp,它是生成 crc32ra.asm 使用的常量的程序。
执行 64 位 CRC 时会出现另一个问题。对于非反射CRC,有时常数是65位(例如,如果除数是7),但仅存储低64位,并且2^64位用更多指令处理。对于反射 64 位 CRC,由于常数不能左移,因此使用 (x^(a-1) mod poly) 代替。