探究CRC32算法实现原理-why table-driven implemention

来源:互联网 发布:110kv地下变电站 知乎 编辑:程序博客网 时间:2024/06/02 05:29

探究CRC32算法实现原理-why table-driven implemention

http://www.cppblog.com/kevinlynx/archive/2008/04/01/45952.html


Preface

基于不重造轮子的原则,本文尽量不涉及网络上遍地都是的资料。

What's CRC ?

简而言之,CRC是一个数值。该数值被用于校验数据的正确性。CRC数值简单地说就是通过让你需要做
处理的数据除以一个常数而得到的余数。当你得到这个数值后你可以将这个数值附加到你的数据后,
当数据被传送到其他地方后,取出原始数据(可能在传送过程中被破坏)与附加的CRC数值,然后将这里
的原始数据除以之前那个常数(约定好的)然后得到新的CRC值。比较两个CRC值是否相等即可确认你的
数据是否在传送过程中出现错误。

那么,如何让你的数据除以一个常数?方法是对你的数据进行必要的编码处理,逐字节处理成数字。
那么这个常数是什么?你不必关注它是什么,也不需要关注它是如何获得的。当你真的要动手写一个
CRC的实现算法时,我可以告诉你,CRC的理论学家会告诉你。不同长度的常数对应着不同的CRC实现算法。
当这个常数为32位时,也就是这里所说的CRC32。

以上内容你不必全部理解,因为你需要查阅其他资料来获取CRC完整的理论介绍。

The mathematics behind CRC ?

很多教科书会把CRC与多项式关联起来。这里的多项式指的是系数为0或1的式子,例如:
a0 + a1*x + a2*x^2 + ... + an*x^n。其中a0, a1, ..., an要么为0要么为1。我们并不关注x取什么值。
(如果你要关注,你可以简单地认为x为2) 这里把a0, a1, ..., an的值取出来排列起来,就可以表示比特
流。例如 1 + x + x^3所表示的比特流就为:1101。部分资料会将这个顺序颠倒,这个很正常。

什么是生成多项式?

所谓的生成多项式,就是上面我所说的常数。注意,在这里,一个多项式就表示了一个比特流,也就是一堆
1、0,组合起来最终就是一个数值。例如CRC32算法中,这个生成多项式为:
c(x) = 1 + x + x^2 + x^4 + x^5 + x^7 + x^8 + x^10 + x^11 + x^12 + x^16 + x^22 + x^23 + x^26 + x^32。
其对应的数字就为:11101101101110001000001100100000(x^32在实际计算时隐含给出,因此这里没有包含它
的系数),也就是0xEDB88320(多项式对应的数字可能颠倒,颠倒后得到的是0x04C11DB7,其实也是正确的)。

由此可以看出,CRC值也可以看成我们的数据除以一个生成多项式而得到的余数。

如何做这个除法?

套用大部分教科书给出的计算方法,因为任何数据都可以被处理成纯数字,因此,在某种程度上说,我们可以
直接开始这个除法。尽管事实上这并不是标准的除法。例如,我们的数据为1101011011(方便起见我直接给二进制
表示了,从这里也可以看出,CRC是按bit进行计算的),给定的生成多项式(对应的值)为10011。通常的教科书
会告诉我们在进行这个除法前,会把我们的数据左移几位(生成多项式位数-1位),从而可以容纳将来计算得到
的CRC值(我上面所说的将CRC值附加到原始数据后)。但是为什么要这样做?我也不知道。(不知道的东西不能含糊
而过)那么,除法就为:
            1100001010
       _______________
10011 ) 11010110110000 附加了几个零的新数据
        10011......... 这里的减法(希望你不至于忘掉小学算术)是一个异或操作
        -----.........
         10011........
         10011........
         -----........
          00001....... 逐bit计算
          00000.......
          -----.......
           00010......
           00000......
           -----......
            00101.....
            00000.....
            -----.....
             01011....
             00000....
             -----....
              10110...
              10011...
              -----...
               01010..
               00000..
               -----..
                10100.
                10011.
                -----.
                 01110
                 00000
                 -----
                  1110 = 这个余数也就是所谓的CRC值,通常又被称为校验值。

希望进行到这里,你可以获取更多关于CRC的感性认识。而我们所要做的,也就是实现一个CRC的计算算法。
说白了,就是提供一个程序,给定一段数据,以及一个生成多项式(对于CRC32算法而言该值固定),然后
计算得出上面的1110余数。

The simplest algorithm.

最简单的实现算法,是一种模拟算法。我们模拟上面的除法过程,遵从网上一份比较全面的资料,我们设定
一个变量register。我们逐bit地将我们的数据放到register中。然后判断register最高位是否为1,如果是
则与生成多项式异或操作,否则继续处理。这个过程简单地模拟了上述除法过程:

 

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........///
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
/// The simplest CRC implement algorithm.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
///

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算......../*
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   Load the register with zero bits.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   Augment the message by appending W zero bits to the end of it.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   While (more message bits)
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Begin
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Shift the register left by one bit, reading the next bit of the
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........         augmented message into register bit position 0.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      If (a 1 bit popped out of the register during step 3)
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........         Register = Register XOR Poly.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      End
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   The register now contains the remainder.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
*/

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <stdio.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#define POLY 0x13
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........int main()
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the data 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned short data = 0x035b;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// load the register with zero bits
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned short regi = 0x0000;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// augment the data by appending W(4) zero bits to the end of it.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ data <<= 4;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// we do it bit after bit
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint cur_bit = 15; cur_bit >= 0; -- cur_bit )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// test the highest bit which will be poped later.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  
/// in fact, the 5th bit from right is the hightest bit here

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  if( ( ( regi >> 4 ) & 0x0001 ) == 0x1 )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   regi = regi ^ POLY;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// shift the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi <<= 1;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// reading the next bit of the augmented data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  unsigned short tmp = ( data >> cur_bit ) & 0x0001;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi |= tmp;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// and now, register contains the remainder which is also called CRC value.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........


better algorithm ?

很多时候这种让人容易理解的算法都不会被实际用到。这种逐bit操作的算法实在很慢。你可能知道
一般的CRC32算法都是一种基于表(table-driven)的算法。但是你可能不知道这个表是如何来的。

一种改善这种bit after bit的方法就是将这个bit扩大,例如典型的做法就是换成byte。这里我要详细地叙述下
上面那种算法的过程:

我们每次会先检查register的最高位是否为1,如果为1,则将生成多项式(所谓的Poly)与register进行异或操作。
然后,将register左移一位,也就舍弃了最高位。然后将我们的数据拿一bit出来放到register的最低位。

也就是说,register中的某一位的值会决定后面几位的值。如果将register最高字节每一bit编码为:
t7 t6 t5 t4 t3 t2 t1 t0。那么,t7会决定t6-t0的值(如果为1),t6会决定t5-t0的值,依次类推。但是,无论谁
决定谁的值,当上面那个算法迭代一个字节后(8bits),t7-t0都会被丢弃(whatever you do)。唯一留下来的东西,
就是对这个字节以后字节的影响。

那么,如果我们可以直接获取这个影响,我们就可以byte after byte地处理,而不是bit after bit。如何获取这个
影响呢?这个影响又是什么呢?这个影响就对应着我们的table-driven CRC算法中的表元素!

但是,为什么我们逐bit进行计算的过程为什么可以简化为一步操作?事实上,我们没有简化这个操作。一种用于教学
的算法,是实时地计算这个影响值:

 

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........///
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
/// The table-driven CRC implement algorithm part 1.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
///

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算......../*
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  While (augmented message is not exhausted)
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Begin
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Examine the top byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Calculate the control byte from the top byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Sum all the Polys at various offsets that are to be XORed into
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........         the register in accordance with the control byte
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Shift the register left by one byte, reading a new message byte
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........         into the rightmost byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      XOR the summed polys to the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      End
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
*/

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <stdio.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <stdlib.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <memory.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#define POLY 0x04C11DB7L
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........int main()
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the data 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long data = 0x1011035b;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// load the register with the data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long regi = 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// allocate memory to contain the AUGMENTED data (added some zeros)
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned char p[8];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// copy data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ memset( p, 0, 8 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ memcpy( p, &data, 4 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// because data contains 4 bytes
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint i = 0; i < 8; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// get the top byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  unsigned char top_byte = (unsigned char)( ( regi >> 24 ) & 0xff );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// sum all the polys at various offsets 探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  unsigned long sum_poly = top_byte << 24;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  forint j = 0; j < 8; ++ j )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   /// check the top bit
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   if( ( sum_poly >> 31 ) != 0 )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........    /// TODO : understand why '<<' first
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
    sum_poly = ( sum_poly << 1 ) ^ POLY;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
   }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   else
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........    sum_poly <<= 1;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// shift the register left by on byte, reading a new 探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi = ( ( regi << 8 ) | p[i] );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// xor the summed polys to the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi ^= sum_poly;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// and now, register contains the remainder which is also called CRC value.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........


其中:

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算......../// sum all the polys at various offsets 探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  unsigned long sum_poly = top_byte << 24;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  forint j = 0; j < 8; ++ j )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   /// check the top bit
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   if( ( sum_poly >> 31 ) != 0 )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........    /// TODO : understand why '<<' first
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
    sum_poly = ( sum_poly << 1 ) ^ POLY;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
   }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   else
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........    sum_poly <<= 1;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........

  
就是用于计算这个影响值的。事实上,table-driven CRC算法中的那个表就是通过这段代码生成的(排除其他一些细节)。
你可能并不是很理解,这里我建议你忽略各种细节(更多的细节见参考资料)。你所需要知道的是,我们将8次逐bit的操
作合并到了一次byte操作中。而这个byte操作,就是8次bit操作的合操作(上面提到的影响值)。这个byte操作其实就是
一个数值,也就是table-driven CRC算法中那个表的一个元素。不同序列的bit操作其实对应着不同的unsigned char
值,因此那个table有256个元素。

show me where the table is :

如上所说,上面的算法很容易地就可以引进一个表:


进一步简化:

上述算法一个典型特征是会在我们的数据后面添加若干0。这样做其他做了很多没用的计算。一种简化做法就是将这些
没用的计算合并到其他计算中。其实这都是一些位操作的技巧:

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........///
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
/// The table-driven CRC implement algorithm part 2.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
///

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算......../*
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  While (augmented message is not exhausted)
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Begin
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Examine the top byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Calculate the control byte from the top byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Sum all the Polys at various offsets that are to be XORed into
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........         the register in accordance with the control byte
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      Shift the register left by one byte, reading a new message byte
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........         into the rightmost byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      XOR the summed polys to the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........      End
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
*/

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <stdio.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <stdlib.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <memory.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#define POLY 0x04C11DB7L
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........unsigned long get_sum_poly( unsigned char top_byte )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// sum all the polys at various offsets 探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long sum_poly = top_byte << 24;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint j = 0; j < 8; ++ j )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// check the top bit
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  if( ( sum_poly >> 31 ) != 0 )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   /// TODO : understand why '<<' first
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
   sum_poly = ( sum_poly << 1 ) ^ POLY;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
  }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  else
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   sum_poly <<= 1;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return sum_poly;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........void create_table( unsigned long *table )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint i = 0; i < 256; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  table[i] = get_sum_poly( (unsigned char) i );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........int main()
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the data 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long data = 0x1011035b;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// load the register with the data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long regi = 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// allocate memory to contain the AUGMENTED data (added some zeros)
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned char p[8];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// copy data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ memset( p, 0, 8 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ memcpy( p, &data, 4 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the table
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long table[256];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// create the table
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ create_table( table );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// because data contains 4 bytes
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint i = 0; i < 8; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// get the top byte of the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  unsigned char top_byte = (unsigned char)( ( regi >> 24 ) & 0xff );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// shift the register left by on byte, reading a new 探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi = ( ( regi << 8 ) | p[i] );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// xor the summed polys to the register
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi ^= table[top_byte];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// and now, register contains the remainder which is also called CRC value.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........

 

讨厌的附加0

以上算法有个很大的特征就是要为我们的数据附加很多0。附加0后其实也附加了很多无用的操作。我们要将这些
讨厌的0去掉:

 

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........int main()
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the data 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long data = 0x1011035b;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// load the register with the data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long regi = 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// allocate memory to contain the data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned char p[4];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// copy data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ memcpy( p, &data, 4 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the table
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long table[256];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// create the table
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ create_table( table );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// because data contains 4 bytes
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint i = 0; i < 4; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi = ( regi << 8 ) ^ table[ ( regi >> 24 ) ^ p[i] ];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// and now, register contains the remainder which is also called CRC value.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........


关键的一句regi = ( regi << 8 ) ^ table[ ( regi >> 24 ) ^ p[i] ]; 简化了很多没用的操作。


In practice :

似乎一切被我说的很简单。我想只是因为我没说清楚。我尽量让你注意到事情的重点。我们进行到这里,似乎
我们立马就可以写出自己的CRC32算法并用于实践。但是你很快就会发现,事情并不如你想像的那么简单。

在实际处理时,很多数据的bit会进行一种颠倒操作,例如1010会被颠倒为0101。出现这样的情况是因为某些硬件
在实现CRC算法时,采用了这种(丑陋的)习惯。有些软件实现CRC算法时,也延用了这个习惯。

另外,关于register的初始值问题,有些CRC算法会初始化为0xffffffff。以下给出一个会进行bit颠倒的算法,
该算法可以直接输出table-driven中的表:

 

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........///
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
/// The table-driven CRC implement algorithm part 4.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
///
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
/// Donot need augment W/8 zero bytes.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
///

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <stdio.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <stdlib.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#include <memory.h>
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#define POLY 0x04C11DB7L
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........#define BITMASK(X) (1L << (X))
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........unsigned long refelect( unsigned long v, int b )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ int   i;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long  t = v;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ for( i = 0; i < b; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  if( t & 1L )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   v |=  BITMASK( (b-1)-i );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  else
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   v &= ~BITMASK( (b-1)-i );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  t >>= 1;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return v;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算......../// i'll try to write a correct algorithm
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........unsigned long get_sum_poly( unsigned char byte )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ byte = (unsigned long) refelect( byte, 8 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long sum_poly = byte << 24;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint i = 0; i < 8; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  /// check the top bit
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  if( ( sum_poly >> 31 ) != 0 )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   /// TODO : understand why '<<' first
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
   sum_poly = ( sum_poly << 1 ) ^ POLY;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
  }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  else
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   sum_poly <<= 1;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ sum_poly = refelect( sum_poly, 32 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return sum_poly;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........void create_table( unsigned long *table )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint i = 0; i <= 255; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  table[i] = get_sum_poly( (unsigned char) i );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........void output_table( const unsigned long *table )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ FILE *fp = fopen( "table.txt", "w" );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint y = 0; y < 64; ++ y )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  fprintf( fp, "0x%08lXL,\t0x%08lXL,\t0x%08lXL,\t0x%08lXL, \n", 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   table[ y * 4 + 0], 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   table[ y * 4 + 1], 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   table[ y * 4 + 2], 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........   table[ y * 4 + 3] );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ fclose( fp );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........int main()
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........{
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the table
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long table[256];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// the data 
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long data = 0x1011035b;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// load the register with the data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned long regi = 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// allocate memory to contain the data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ unsigned char p[4];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// copy data
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ memcpy( p, &data, 4 );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// create the table
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ create_table( table );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// output the table
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ output_table( table );
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// because data contains 4 bytes
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ forint i = 0; i < 4; ++ i )
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ {
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........  regi = ( regi << 8 ) ^ table[ ( regi >> 24 ) ^ p[i] ];
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ }

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ /// and now, register contains the remainder which is also called CRC value.
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........ return 0;
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........}

探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........
探究CRC32算法实现原理-why table-driven implemention - cruelchen - 请重启您的计算........


Please FORGIVE me

我想我并没有将整个过程彻底地讲清楚。但是我希望你能明白大致的原理。关于table-driven中那个神奇的表的来历,
关于CRC32算法的推导过程等等之类。


本文代码下载: http://www.cppblog.com/Files/kevinlynx/CRC%20Implement.rar

参考资料:
http://www34.brinkster.com/dizzyk/math-crc.asp
http://www.greenend.org.uk/rjk/2004/crc.html
http://www.ross.net/crc/crcpaper.html

 


原创粉丝点击