浅谈crc32反转与不反转的公式理解

  • List item

CRC闲谈

此处介绍为CRC_32查表法的代码解释,个人理解,非专业

设置一个4字节数据,每字节分别设置为a ,b, c, d,当前数据为a b c d
a b c d分别为16进制数据

多项式为:04C11DB7

初始值为:0xFFFFFFFF

首先声明CRC支持结合律,这个网上搜,不再介绍,也可自己实践

a b c d

按照手算方法,是一位一位的移动,是零忽略,是一 移位,和04C11DB7异或

Crc_32输入输出不反转介绍

查表法
声明:下面的x?仅代表第几个byte,不涉及数据
第一步
先算a ,忽略b c d
算出来的应该为
在这里插入图片描述

ax1 ax2 ax3 ax4 为a对应的CRC,记作a’,a’可以通过查表获得

则此项可以看做
在这里插入图片描述

第二步
然后算b的CRC
在这里插入图片描述

因为受到a’的影响
b这项的数据应为b xor ax1,记作b1,则b1=(a’>>24) xor b ,只需要取一个字节,即b1=((a’>>24) xor b) & 0xff

则得出的数据应为
在这里插入图片描述

如上所示:
因为a’的影响,此crc并不完全,合并运算b运算完成后的crc第一位依次为应该为 ax2 xor b1x1 ax3 xor b1x2 ax4 xor b1x3 b1x4
即b’=b1’ xor (a’ <<8)

第三步
则数据应为

同理,c1==((b’>>24) xor c) & 0xff,c’=c1’ xor (b’ <<8),

结论
所以查表法的代码为crc_new = Crc32Table[((crc>>24)^data[i]) & 0xff] ^ (crc << 8);
以计算b的crc举例子
Crc32Table[((crc>>24)^data[i]) & 0xff]代表查表法出来的数据,b1’,其中crc代表上次的crc,a’.

下附代码

//下面代码中dword相当于unsigned int
dword Crc32Table[256];

dword bitrev( dword input, int bw)//位反转
{
    int i;
    dword var;
    var = 0;
    for(i=0;i<bw;i++)
    {
        if(input & 0x01)
        {
            var |= 1<<(bw-1-i);
        }
        input>>=1;
    }
    return var;
}

void make_table()//制作无反转码表
{
  int i;
  int j;
  qword c;
  
  qword poly=0x4C11DB7;
  poly = bitrev(poly, 32);
  for (i = 0; i<256; i++) // 0x00-0xFF
  {
    c = bitrev(i,8);
    for (j = 0; j<8; j++) // bit 0-7
    {
      if (c & 1)
      {
        c = poly ^ (c >> 1);
      }
      else
      {
        c = c >> 1;
      }
    }
    Crc32Table[i] = bitrev(c,32);
  }
}


dword crc32(byte data[], dword len)//输入byte数组data[],len为data[]的长度
{
  dword i =0;
  for (i = 0; i < len; i++)
  {
     crc = Crc32Table[((crc>>24)^data[i]) & 0xff] ^ (crc << 8);
  }
  return crc;
}

Crc_32输入输出反转介绍

查表法
声明:下面的x?仅代表第几个bit,不涉及数据**(注意:与上面有区别)**

因为有上面例子,此次举例子只有两个数字a b
设a b 的逆转数据为a* b*
获取a的crc,
在这里插入图片描述

对a取反,根据
在这里插入图片描述

对a’取反,
在这里插入图片描述

但是在实际用手算法进行时,输出取反只在最后一次,即如此
在这里插入图片描述

计算b的crc,首先要对b取反,即
在这里插入图片描述

计算b的crc时因为受到a’的影响
在这里插入图片描述

b8_1表示收到影响之后的值
B8_1=b7 xor ax1
b7_1=b7 xor ax2
b6_1=b6 xor ax3

b1_1=b1 xor ax8

对上面这个b_1进行取crc,不方便看,将a简写了
在这里插入图片描述

其中ax9-ax32分别与b_1x1-b_1x24分别对应

最终b’应为b_1x1 xor ax9 … b_1x24 xor ax32
即b’=(a’<<8) xor b_1’
其中b_1’可以通过查表得到

以上对crc_32输入反转有了一个认识,并清楚运算原理了,但是经常使用的生成表一般是在生成过程中进行了输入反转的同时也进行了输出反转,所以不需要人为操作

即对a运算
a’= ( ax32 ax31 ax30 ax29 … ax1 )
这样的话和上面出现了差别
这样的话
在这里插入图片描述

以上是输出反转后对应的情况,对应情况还是这样不能变化,以为手动运算就是这样运算的
这样的话因为受到a*’的影响,b对应的数据b_1应为 b1 xor ax8 --------- b8 xor ax1
对b_1查表取出crc应为
这一行是为了看上面的对应关系,不要太深入,没有特殊的意思
在这里插入图片描述

这个图看起来可能看不懂
其实应该这样,先抛弃,a和b这一行,不然无法看起来更懵
在这里插入图片描述

按照上面计算的ax9-ax32分别与b_1x1-b_1x24分别对应
就是b*’=(a*’>>8) xor b*’

综上:crc_new = Crc32Table[(crc ^ data[i]) & 0xff] ^ (crc >> 8); 其中Crc32Table[(crc ^ data[i]) & 0xff]为查表得出的数据,b*’,crc 为上次的crc,a*’ .
这个公式的意思是:(crc ^ data[i]) & 0xff根据当前data[i]的值算出受上个byte传来的crc影响后的数据crc ^ data[i],因为一个byte只有8bit,所以& 0xff
根据b*’=(a*’>>8) xor b*,对应出来的为Crc32Table[(crc ^ data[i]) & 0xff] ^ (crc >> 8)即为当前crc反转的值

代码如下

dword Crc32Table[256];

dword bitrev( dword input, int bw)//反转
{
    int i;
    dword var;
    var = 0;
    for(i=0;i<bw;i++)
    {
        if(input & 0x01)
        {
            var |= 1<<(bw-1-i);
        }
        input>>=1;
    }
    return var;
}

void make_table()//制作码表
{
  int i;
  int j;
  qword c;
  
  qword poly=0x4C11DB7;
  poly = bitrev(poly, 32);
  for (i = 0; i<256; i++) // 0x00-0xFF
  {
  	c=i & 0xff;
    for (j = 0; j<8; j++) // bit 0-7
    {
      if (c & 1)
      {
        c = poly ^ (c >> 1);
      }
      else
      {
        c = c >> 1;
      }
    }
    Crc32Table[i] = c;
  }
}

dword crc32(byte data[], dword len)//输入反转,输出反转
{
  dword i =0;
  for (i = 0; i < len; i++)
  {
     crc = Crc32Table[(crc ^ data[i]) & 0xff] ^ (crc >> 8);
  }
  writeLineEx(mNewPage,1,"CRC  %08x",crc);
  return crc;
}


以上仅仅是个人的见解,与实际文档可能存在差距,仅供参考,如有转载,请备注链接。

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值