程序可以如下实现:
1)将Mx^r的前r位放入一个长度为r的寄存器;
2)如果寄存器的首位为1,将寄存器左移1位(将Mx^r剩下部分的MSB移入寄存器的LSB),
再与G的后r位异或,否则仅将寄存器左移1位(将Mx^r剩下部分的MSB移入寄存器的LSB);
3)重复第2步,直到M全部Mx^r移入寄存器;
4)寄存器中的则为校验码。
基于以上算法,我们可以看一下上面例子的程序计算过程:(r=3)
首先,111 00110000前三位进入寄存器,即111
这时寄存器首位为1,执行第2步,移位成110 0110000,这时寄存器中为前三位110,将其与011(生成多项式后三位)异或,得101 0110000.
然后继续第2步,101首位为1,移位010 110000,然后010与011异或,得 001 110000
前面两个0,连续以为2次且不用计算异或,得111 0000,接着移位110 000,异或得101 000
第一位为1,移位得010 00,前三位异或得001 00
最后因为前面两个0,直接移位两次后得寄存器中的内容100,这时Mx^r位的所有内容都移入寄存器,运算结束,记得检验码为100。(关键先判断首位是否为1,然后移位,然后计算)
111 00110000移位->1 110 0110000
011
101 0110000 -->101第一位为1,移位且计算
1 010 110000
011
001 110000-->001第一位第二位均为0,移位2次
00 111 0000-->111第一位为1,移位且计算
1 110 000
011
101 000-->101第一位为1,移位且计算
1 010 00
011
001 00-->移位2次得100
用CRC16-CCITT的生成多项式0x1021,其C代码(本文所有代码假定系统为32位,且都在VC6上编译通过)如下:
unsigned short do_crc(unsigned char *message, unsigned int len)
{
int i, j;
unsigned short crc_reg;
crc_reg = (message[0] << 8) message[1];
for (i = 0; i < len; i)
{
if (i < len - 2)
for (j = 0; j <= 7; j)
{
if ((short)crc_reg < 0)
crc_reg = ((crc_reg << 1) (message[i 2] >> (7 - i))) ^ 0x1021;
else
crc_reg = (crc_reg << 1) (message[i 2] >> (7 - i));
}
else
for (j = 0; j <= 7; j)
{
if ((short)crc_reg < 0)
crc_reg = (crc_reg << 1) ^ 0x1021;
else
crc_reg <<= 1;
}
}
return crc_reg;
}
显然,每次内循环的行为取决于寄存器首位。循环冗余校验由于异或运算满换率和结合律,以及与0异或无影响,消息可以不移入寄存器,而在每次内循环的时候,寄存器首位再与对应的消息位异或。改进的代码如下:
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-38614-2.html
最低应该鸣炮警告