CRC算法简介
循环冗余校验码(CRC),简称循环码,是一种常用的、具有检错、纠错能力 的校验码,在通信中运用广泛。
CRC 计算可以靠专用的硬件来实现,但是对于低 成本的微控制器系统,在没有硬件支持下实现 CRC 检验,关键的问题就是如何通 过软件来完成 CRC 计算,也就是计算 CRC 校验和的问题。
CRC 校验的基本思想
利用线性编码理论,将发送端要传送的 K 位二进制码序列以一定的规则产生一 个校验用的 R 位监督码(既 CRC 码),并附在信息后边,构成一个新的(K+R)位 二进制码序列,并最后发送出去。在接收端则根据信息码和 CRC 码之间所遵循的 规则进行校验,以确定传送中是否出错。
CRC 码是一种线性、分组的系统码。在 K 位信息码之后再拼接 R 位的校码,
整个编码长度为 N(N=K+R)位,因此,这种编码又叫(N,K)码。CRC 校验采用多项式编码的方法,被处理的 n 比特的数据块可以看作是一个 n-1 阶的二进制多项式
例如,数据 1010111 对应的多项式为 x6+x4+x2+x+1,而多项式 x5+x3+x2+x+1
对应的数据为 101111。
多项式乘除法运算过程与普通代数多项式的乘除法相同。多项式的加减法运
算以 2 为模,加减时不进、借位,和逻辑异或运算一致。
其中模 2 除步骤如下:
(1)用除数对被除数最高几位做模 2 减,没有借位。
(2)除数右移一位,若余数最高位为 1,商为 1,并对余数做模 2 减。若余
数最高位为 0,商为 0,除数继续右移一位。
(3)一直做到余数的位数小于除数时,该余数就是最终余数。
CRC32的计算
要生成 CRC 码首先要将待发送的二进制数据 C(X)左移 R 位,然后除以生成多 项式 G(X),这样得到的余数就是 CRC 码。CRC 码的具体生成步骤如下:
(1)将 x 的最高幂次为 R 的生成多项式 G(X)转换成对应的 R+1 位二进制数。
(2)将待发送的二进制数据 C(X)左移 R 位,相当于对应的信息多项式
C(X)*2
(3)用生成多项式(二进制数)对信息码做模 2 除,得到 R 位的余数 R(X)
(4)将余数拼接到信息码左移后空出的位置,得到完整的 CRC 码。
例如,假设使用的生成多项式是 G(X)=x3+x+1,4 位的原始报文为 1010,求
编码后的报文。解的过程如下所示:
(1)将生成多项式 G(X)=x3+x+1 转换成对应的二进制数 1011.
(2)生成多项式有 4 位,要把原始报文 C(X)左移 3 位变为 1010 000.
(3)用生成多项式对应的二进制数对左移 3 位后的原始报文进行模 2 除。
(4)得到余数 011,即校验码。
(5)编码后的报文(CRC 码)为 1010 011
CRC-32 的生成多项式如式(1)所示。
所以其对应二进制数为 00000001 00000100 11000001 00011101 10110111,
转化为 16 进制后为 04C11DB7H。
查表法实现CRC32校验码的计算
(1)将上次循环计算出的CRC和一个字节进行XOR 运算;
(2)用运算出的值和0xff进行按位与运算;
(3)将第二步运算出的值去查表;
(4)将上次循环计算出的CRC右移八位;
(5)将右移八位的CRC和第三步查找的结果进行XOR运算
(6)循环处理所有数据
(7)将得到的CRC再和0xFFFFFFFF进行XOR运算
实验代码
(vs2019下)
.data
array label dword
dd 000000000h,077073096h,0EE0E612Ch,0990951BAh,0076DC419h,0706AF48Fh,0E963A535h,09E6495A3h
dd 00EDB8832h,079DCB8A4h,0E0D5E91Eh,097D2D988h,009B64C2Bh,07EB17CBDh,0E7B82D07h,090BF1D91h
dd 01DB71064h,06AB020F2h,0F3B97148h,084BE41DEh,01ADAD47Dh,06DDDE4EBh,0F4D4B551h,083D385C7h
dd 0136C9856h,0646BA8C0h,0FD62F97Ah,08A65C9ECh,014015C4Fh,063066CD9h,0FA0F3D63h,08D080DF5h
dd 03B6E20C8h,04C69105Eh,0D56041E4h,0A2677172h,03C03E4D1h,04B04D447h,0D20D85FDh,0A50AB56Bh
dd 035B5A8FAh,042B2986Ch,0DBBBC9D6h,0ACBCF940h,032D86CE3h,045DF5C75h,0DCD60DCFh,0ABD13D59h
dd 026D930ACh,051DE003Ah,0C8D75180h,0BFD06116h,021B4F4B5h,056B3C423h,0CFBA9599h,0B8BDA50Fh
dd 02802B89Eh,05F058808h,0C60CD9B2h,0B10BE924h,02F6F7C87h,058684C11h,0C1611DABh,0B6662D3Dh
dd 076DC4190h,001DB7106h,098D220BCh,0EFD5102Ah,071B18589h,006B6B51Fh,09FBFE4A5h,0E8B8D433h
dd 07807C9A2h,00F00F934h,09609A88Eh,0E10E9818h,07F6A0DBBh,0086D3D2Dh,091646C97h,0E6635C01h
dd 06B6B51F4h,01C6C6162h,0856530D8h,0F262004Eh,06C0695EDh,01B01A57Bh,08208F4C1h,0F50FC457h
dd 065B0D9C6h,012B7E950h,08BBEB8EAh,0FCB9887Ch,062DD1DDFh,015DA2D49h,08CD37CF3h,0FBD44C65h
dd 04DB26158h,03AB551CEh,0A3BC0074h,0D4BB30E2h,04ADFA541h,03DD895D7h,0A4D1C46Dh,0D3D6F4FBh
dd 04369E96Ah,0346ED9FCh,0AD678846h,0DA60B8D0h,044042D73h,033031DE5h,0AA0A4C5Fh,0DD0D7CC9h
dd 05005713Ch,0270241AAh,0BE0B1010h,0C90C2086h,05768B525h,0206F85B3h,0B966D409h,0CE61E49Fh
dd 05EDEF90Eh,029D9C998h,0B0D09822h,0C7D7A8B4h,059B33D17h,02EB40D81h,0B7BD5C3Bh,0C0BA6CADh
dd 0EDB88320h,09ABFB3B6h,003B6E20Ch,074B1D29Ah,0EAD54739h,09DD277AFh,004DB2615h,073DC1683h
dd 0E3630B12h,094643B84h,00D6D6A3Eh,07A6A5AA8h,0E40ECF0Bh,09309FF9Dh,00A00AE27h,07D079EB1h
dd 0F00F9344h,08708A3D2h,01E01F268h,06906C2FEh,0F762575Dh,0806567CBh,0196C3671h,06E6B06E7h
dd 0FED41B76h,089D32BE0h,010DA7A5Ah,067DD4ACCh,0F9B9DF6Fh,08EBEEFF9h,017B7BE43h,060B08ED5h
dd 0D6D6A3E8h,0A1D1937Eh,038D8C2C4h,04FDFF252h,0D1BB67F1h,0A6BC5767h,03FB506DDh,048B2364Bh
dd 0D80D2BDAh,0AF0A1B4Ch,036034AF6h,041047A60h,0DF60EFC3h,0A867DF55h,0316E8EEFh,04669BE79h
dd 0CB61B38Ch,0BC66831Ah,0256FD2A0h,05268E236h,0CC0C7795h,0BB0B4703h,0220216B9h,05505262Fh
dd 0C5BA3BBEh,0B2BD0B28h,02BB45A92h,05CB36A04h,0C2D7FFA7h,0B5D0CF31h,02CD99E8Bh,05BDEAE1Dh
dd 09B64C2B0h,0EC63F226h,0756AA39Ch,0026D930Ah,09C0906A9h,0EB0E363Fh,072076785h,005005713h
dd 095BF4A82h,0E2B87A14h,07BB12BAEh,00CB61B38h,092D28E9Bh,0E5D5BE0Dh,07CDCEFB7h,00BDBDF21h
dd 086D3D2D4h,0F1D4E242h,068DDB3F8h,01FDA836Eh,081BE16CDh,0F6B9265Bh,06FB077E1h,018B74777h
dd 088085AE6h,0FF0F6A70h,066063BCAh,011010B5Ch,08F659EFFh,0F862AE69h,0616BFFD3h,0166CCF45h
dd 0A00AE278h,0D70DD2EEh,04E048354h,03903B3C2h,0A7672661h,0D06016F7h,04969474Dh,03E6E77DBh
dd 0AED16A4Ah,0D9D65ADCh,040DF0B66h,037D83BF0h,0A9BCAE53h,0DEBB9EC5h,047B2CF7Fh,030B5FFE9h
dd 0BDBDF21Ch,0CABAC28Ah,053B39330h,024B4A3A6h,0BAD03605h,0CDD70693h,054DE5729h,023D967BFh
dd 0B3667A2Eh,0C4614AB8h,05D681B02h,02A6F2B94h,0B40BBE37h,0C30C8EA1h,05A05DF1Bh,02D02EF8Dh
bufstr1 DB 'please enter a string:',10,0
bufstr3 DB 'crc 32 is :',10,0
n byte '%s',0
bufstr2 byte 11 dup(0)
n2 byte '%x',10,0
index dword ?
input dword ?
crc dword ?
.code
main proc
mov edx,offset array
pushad
invoke printf,offset bufstr1
invoke scanf,offset n,offset bufstr2
popad
xor eax,eax ;保存bufstr2中的每一个元素
xor ecx,ecx
mov ebx,0FFFFFFFFh ;保存crc的值
mov esi,0 ;循环遍量
.while(esi<10)
mov al,bufstr2[esi]
sub eax,'0' ;得到相应的数字
mov ecx,ebx ;保存ebx的值,防止被异或操作污染
xor ecx,eax
and ecx,000000ffh
mov ecx,[edx+ecx*4]
shr ebx,8
xor ebx,ecx
inc esi ;修改循环变量
.endw
xor ebx,0ffffffffh
pushad
invoke printf,offset bufstr3
invoke printf,offset n2,ebx
popad
ret
main endp
end main
实验截图