Итак, у меня есть проект, который включает контрольные суммы CRC32C, чтобы гарантировать, что данные не были повреждены. Я решил использовать CRC32C, потому что я могу иметь как версию программного обеспечения, так и версию с аппаратным ускорением, если компьютер, на котором работает программное обеспечение, поддерживает SSE 4.2
Я собираюсь с помощью руководства разработчика Intel (vol 2A), который, как представляется, обеспечивает алгоритм, лежащий в основе инструкции crc32
. Тем не менее, у меня мало шансов. Руководство разработчика Intel говорит следующее:
BIT_REFLECT32: DEST[31-0] = SRC[0-31]
MOD2: Remainder from Polynomial division modulus 2
TEMP1[31-0] <- BIT_REFLECT(SRC[31-0])
TEMP2[31-0] <- BIT_REFLECT(DEST[31-0])
TEMP3[63-0] <- TEMP1[31-0] << 32
TEMP4[63-0] <- TEMP2[31-0] << 32
TEMP5[63-0] <- TEMP3[63-0] XOR TEMP4[63-0]
TEMP6[31-0] <- TEMP5[63-0] MOD2 0x11EDC6F41
DEST[31-0] <- BIT_REFLECT(TEMP6[31-0])
Теперь, насколько я могу судить, я делал все до строки, начинающейся с TEMP6
правильно, но я думаю, что я могу либо неправильно понять полиномиальное деление, либо реализовать его неправильно. Если мое понимание верное, 1 / 1 mod 2 = 1
, 0 / 1 mod 2 = 0
, и оба деления на ноль undefined.
Я не понимаю, как будет работать двоичное деление с 64-битными и 33-битными операндами. Если SRC
- 0x00000000
, а DEST
- 0xFFFFFFFF
, TEMP5[63-32]
будут все заданные биты, а TEMP5[31-0]
будут все несохраненные биты.
Если бы я использовал биты из TEMP5
в качестве числителя, было бы 30 делений на ноль, так как многочлен 11EDC6F41
был всего лишь 33 бита (и поэтому преобразование его в 64-разрядное целое без знака выходит из верхние 30 бит не установлены), поэтому знаменатель не установлен на 30 бит.
Однако, если бы я использовал полином в качестве числителя, нижние 32 бита TEMP5
не были отменены, что привело бы к делению на нуль там, а верхние 30 бит результата были бы равны нулю, так как верхние 30 бит числителя будет равен нулю, как 0 / 1 mod 2 = 0
.
Я не понимаю, как это работает? Просто что-то пропало? Или Intel отказалась от некоторых важных шагов в своей документации?
По причине того, что я пошел в руководство разработчика Intel, для того, что, по-видимому, был алгоритмом, который они использовали, заключается в том, что они использовали 33-битный полином, и я хотел сделать вывод идентичным, чего не было, когда я использовал 32-битный полином 1EDC6F41
(показано ниже).
uint32_t poly = 0x1EDC6F41, sres, crcTable[256], data = 0x00000000;
for (n = 0; n < 256; n++) {
sres = n;
for (k = 0; k < 8; k++)
sres = (sres & 1) == 1 ? poly ^ (sres >> 1) : (sres >> 1);
crcTable[n] = sres;
}
sres = 0xFFFFFFFF;
for (n = 0; n < 4; n++) {
sres = crcTable[(sres ^ data) & 0xFF] ^ (sres >> 8);
}
Вышеприведенный код создает 4138093821
в качестве вывода, а код операции crc32
создает 2346497208
с помощью ввода 0x00000000
.
Извините, если это плохо написано или непонятно по местам, это довольно поздно для меня.