该程序是否正确计算 CRC?

问题描述

我正在尝试创建一个函数,该函数采用单个字节并为给定的任何生成的多项式返回 CRC 值。

#include <stdio.h>
#include <stdint.h>

#define MSG_SIZE    7                             // number of message bits
#define poly_SIZE   9                             // number of gen. poly. bits
#define SHIFT_INPUT poly_SIZE-1                   // zeros to be added to input
#define SHIFT_poly  MSG_SIZE-1                    // zeros to be added to polynomial
#define poly        0x11D                          // generated polynomial
#define poly_MSK    (poly << SHIFT_poly)          // add zeros to polynomial to be aligned with input
#define ALIGN_MSK   (1 << (MSG_SIZE+poly_SIZE-2)) // for MSB_poly and MSB_input alignment check

uint64_t PartCRC(uint64_t input);

uint64_t PartCRC(uint64_t input){

    input = ( input << SHIFT_INPUT );

    for(int n = 0; n < MSG_SIZE; n++){
        // if current (MSB) bit of input is "1"; if MSB_poly and MSB_input are aligned
        if( input & ALIGN_MSK ){
            input ^= poly_MSK;      // input XOR poly
        }
        // if crc is calculated,don't shift
        if( n == (MSG_SIZE-1) ) break;
        input = ( input << 1 );       // shift input left each step
    }
    return (input >> SHIFT_poly);   // return crc - trim zeros
}

void main(void) {

    printf( "CRC for input: %llX\n",PartCRC(0x41) );

    return;
}

除了从 PartCRC() 提供给 main() 函数的消息之外,我必须仅将生成的多项式定义为十六进制数加上其大小和消息大小(从 LSB 到 MSB 的位数)。 这个函数的作用是在每次迭代时将输入左移,在那里检查多项式的 MSB 和输入的 MSB 是否对齐;如果是这样,则在当前移位的输入和多项式之间执行按位 XOR(即 poly_MSK - poly 被移位以使其与当前移位的输入对齐)。最后,计算出的余数右移(因为它在 CRC 计算期间用零填充)。

我了解这个过程是如何工作的,我非常有信心它应该对每个 CRC 标准化生成的多项式正确运行,但是它只对少数非标准化多项式起作用。例如,它适用于 2.Introduction 段落(以及少数其他多项式)。

然而,对于其他(标准化的)多项式,它不起作用;在 this 站点检查代码的(非)有效性。在这里,我想指出,我了解关于生成的多项式计算 CRC 的方法很少 - 正态、逆向、倒数、逆倒数。为简单起见,我保持正常表示,并且在前面提到的站点要求已经计算的 CRC 时我也考虑了这一事实(我的意思是“初始值”和“最终 XOR 值”都是 0x00,虽然我不确定,那两个是什么意思)

解决方法

至少有一个潜在问题:整数大小

#define MSG_SIZE    7
#define POLY_SIZE   9   
#define ALIGN_MSK   (1 << (MSG_SIZE+POLY_SIZE-2))

MSG_SIZE+POLY_SIZE-2 超过 15 并且 1 是 16 位 int 时,这是一个问题。同样,对于 MSG_SIZE+POLY_SIZE-2 超过 31 并且 1 是 32 位 int

更好

#define ALIGN_MSK   ((uint64_t)1 << (MSG_SIZE+POLY_SIZE-2))

以下类似问题。

#define POLY        0x11D 
#define POLY_MSK    (POLY << SHIFT_POLY) 
input ^= POLY_MSK;

推荐

#define POLY_MSK    ((uint64_t)POLY << SHIFT_POLY) 

代码对 SHIFT_INPUT 的使用看起来不错,但推荐使用 ()

// #define SHIFT_INPUT POLY_SIZE-1
#define SHIFT_INPUT (POLY_SIZE-1)