再探CRC

时间:2024-07-07 10:05:02

之前写了CRC16的程序,虽说能用,却不知其所心然,现在要用CRC32,重温一遍,一下就通了。笔记如下

CRC我没记错的话是Cyclic Redundancy Code,Cyclic和Redundancy非常传神,所谓冗余就是附加的信息,这就是计算下面的原始数据时为什么原始数据要左移四位的原因,

再探CRC

/************************************************************************
*
* The simplest CRC implement algorithm.
*
************************************************************************/

/************************************************************************
    Load the register with zero bits.
    Augment the message by appending W zero bits to the end of it.
    While (more message bits)
      Begin
      Shift the register left by one bit, reading the next bit of the augmented message into register bit position 0.
      If (a 1 bit popped out of the register during step 3)
         Register = Register XOR Poly.
      End
    The register now contains the remainder.
************************************************************************/

#include <stdio.h>

#define POLY 0x13

int main()
{
    // the data
    unsigned short data = 0x035b;

    // load the register with zero bits
    unsigned short regi = 0x0000;

    // augment the data by appending W(4) zero bits to the end of it.
    data <<= ;

    // we do it bit after bit
    ; cur_bit >= ; -- cur_bit )
    {
        // test the highest bit which will be poped later.
        // in fact, the 5th bit from right is the hightest bit here
         ) & 0x0001 ) == 0x1 )    //凑够5位数(与被除数即生成多项式的位数一样),模2除
        {
            regi = regi ^ POLY;
        }
        // shift the register  regi <<= 1;
        // reading the next bit of the augmented data
        unsigned short tmp = ( data >> cur_bit ) & 0x0001;
        regi |= tmp;

    }

    // and now, register contains the remainder which is also called CRC value.
    ;
}

以上程序就是上面照片里算法的模拟实现,步骤完全一致。

Some popular polys are:

16 bits: (16,12,5,0) [X25 standard]

(16,15,2,0) ["CRC-16"]

32 bits: (32,26,23,22,16,12,11,10,8,7,5,4,2,1,0) [Ethernet]

我们常用的CRC生成多项式如上,如果CRC32校验也要按BIT来计算的话,将是一个多么大的工程。所以一般会以BYTE为单位进行计算,因为计算机的寄存器位数都是8的位数。

我们先来看异或的一个特性,这是我们展开下面描述的基础:

还是照片里的计算例子,这里把首位为0

Original message : 

Poly : 

Message after appending W zeros : 

Now we simply divide the augmented message by the poly using CRC

arithmetic. This is the same division as before:

 = Quotient (nobody cares about the quotient)
        _______________
 )  = Augmented message ( + )
=Poly   ,,.,,....
        -----,,.,,....
        ,.,,....    //每一次的余数就是寄存器里的当前值,这里寄存器已经左移了一位,
                        //读入一位新数据
        ,.,,....
        -----,.,,....
        .,,....    //首位为0,寄存器内值比除数小,则继续读入下一位
        .,,....
        -----.,,....
        ,,....
        ,,....
        -----,,....
        ,....
        ,....
        -----,....
        ....
        ....
        -----....
        ...
        ...
        -----...
        ..
        ..
        -----..
        .
        .
        -----.

        -----
         = Remainder = THE CHECKSUM!!!! 

我们试另一种算法,把数据1101011011以5位一段分开:11010,11011

先对11010做对poly的CRC校验,即110100000模2除poly结果是1000,把1000 0000与110110000异或,得到10110000再模2除poly,结果还是1110与之前的计算结果一样。

看到这里,你可能想到了,把数据按8位一段划分,先对最高位的byte进行CRC校验,校验值与下一byte异或进行校验。。。。。。。,最后我们也得到了CRC校验值。