请教各路Delphi高手,怎样实现CRC校验?(300分)

  • 主题发起人 主题发起人 qlwy
  • 开始时间 开始时间
Q

qlwy

Unregistered / Unconfirmed
GUEST, unregistred user!
CRC校验是网络通讯常用的校验方法,我只知道它将命令码除以生成多项式(用的是模2除法)
得到余数为校验码,并将校验码加在命令码后传输。但是怎么用Delphi编程来实现它呢?尤其
是模2除法更让我一筹莫展,请各位精通此行的高手赐教(最好能给出代码),多谢!
 
模2除法 做减法时为异或
 
CRC校验算法常用的是CRC12、CRC16、CRC32、CRC-CCITT等几种
这主要是根据生成多项式来决定的。详细的校验算法需要去看《现代通信原理》
或《差错控制编码》等编码理论书籍。以下是CRC16算法实现的C代码:

发信人: ie (冷雪·不孝·服丧中), 信区: Programming
标 题: Re: [求教]关于CRC-32(急!) (转载)
发信站: BBS 水木清华站 (Tue Mar 28 08:32:32 2000)

CRC-32的生成多项式是
G(D)=D32+D26+D23+D22+D16+D12+D11+D10+D8+D7+D5+ D4+D2+D+1
由此求出生成矩阵
另外顺便给出其他几个常用CRC的生成多项式
CRC-CCITT: G(D)=D16+D12+D5+1
CRC-16: G(D)=D16+D15+D2+1
CRC-12: G(D)=D12+D11+D3+D2+D+1
(数字在右上角)
这里还有一个CRC-16的程序供参考
file://CRC-16 Bit
file://--------------------------------------------------------------------------
file://--------------------------------------------------------------------------
file://Written by Dmitry S. Obukhov, 1996
file://obukhov@luckynet.co.il
file://--------------------------------------------------------------------------
file://Last modified 6 Apr 97
file://--------------------------------------------------------------------------

file://Add. key FAST_CPU - for CRC table calulation instead of using constants
file://Non-ANSI keywords are C51 specific.
// xdata - variable in external memory
// code - constant in code memory (ROM)
file://If your compiler doesn't support it make #define xdata YOUR_KEYWORD
file://--------------------------------------------------------------------------

#ifdef __BORLANDC__
#define xdata /**/
#define code /**/
#endif
typedef union
{
unsigned int word;
struct
{
unsigned char lo;
unsigned char hi;
}byte;
} LO_HI;
#ifdef FAST_CPU
// Calculate the CRC value for index position i.
unsigned int crc_table(unsigned char i)
{
unsigned int j;
unsigned int k;
unsigned int crc;
k = i << 8;
crc = 0;
for( j = 0; j < 8; j++ )
{
if( ( crc ^ k ) &amp; 0x8000) crc = (crc << 1) ^ 0x1021;
else crc <<= 1;
k <<= 1;
}
return crc;
}
#else
file://This table generated by function crc_table(char)
static unsigned int code CRC_TABLE[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
#endif
static unsigned int crc_iterate(LO_HI crc, unsigned char d)
{
LO_HI temp;
#ifdef FAST_CPU
temp.word = crc_table(crc.byte.hi);
#else
temp.word = CRC_TABLE[crc.byte.hi];
#endif
crc.byte.hi = temp.byte.hi ^ crc.byte.lo;
crc.byte.lo = temp.byte.lo ^ d;
return crc.word;
}
file://This is an entry point for external calls
file://Define this function in the header file
unsigned int count_crc(unsigned char xdata * ptr,
unsigned int count)
{
LO_HI crc,temp;
unsigned int xdata i;
crc.word = 0;
temp.word = 0;
for (i=0;i<count;i++)
{
temp.word = CRC_TABLE[crc.byte.hi];
crc.byte.hi = temp.byte.hi ^ crc.byte.lo;
crc.byte.lo = temp.byte.lo ^ ptr;
}
return crc.word;
}
file://END OF MODULE
在实际中为了减轻运算负荷,加快运算速度,常采用查表方式来完成CRC算法的计算。如上
述代码。

如果算出来有问题欢迎继续讨论
 
VB下如何编写CRC校验程序
作者:栾金奎
  随着计算机技术的不断发展,在现代工业中,利用微机进行数据通讯的工业控制应用
得也越来越广泛。由于传输距离、现场状况等诸多可能出现的因素影响,计算机与受控设
备之间的通讯数据常会发生无法预测的错误。为了防止错误所带来的影响,一般在通讯时
采取数据校验的办法,而循环冗余码校验是最常用的校验方法之一。

一、 循环冗余码校验原理

  循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC。它是利用除法及
余数的原理来作错误侦测(Error Detecting)的。实际应用时,发送装置计算出CRC值并
随数据一同发送给接收装置,接收装置对收到的数据重新计算CRC并与收到的CRC相比较,
若两个CRC值不同,则说明数据通讯出现错误。
根据应用环境与习惯的不同,CRC又可分为以下几种标准:
  ①CRC-12码;
  ②CRC-16码;
  ③CRC-CCITT码;
  ④CRC-32码。
  CRC-12码通常用来传送6-bit字符串。CRC-16及CRC-CCITT码则用是来传送8-bit字符,
其中CRC-16为美国采用,而CRC-CCITT为欧洲国家所采用。CRC-32码大都被采用在一种称为
Point-to-Point的同步传输中。
下面以最常用的CRC-16为例来说明其生成过程。
  CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1,然后把CRC寄存器
与8-bit的数据进行异或,之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补
零,而最低位(LSB,移位后已经被移出CRC寄存器)如果为1,则把寄存器与预定义的多项
式码进行异或,否则如果LSB为零,则无需进行异或。重复上述的由高至低的移位8次,第
一个8-bit数据处理完毕,用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数
据似的8次移位。所有的字符处理完成后CRC寄存器内的值即为最终的CRC值。
  下面为CRC的计算过程:
  1.设置CRC寄存器,并给其赋值FFFF(hex)。
  2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄
存器。
  3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。
  4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码相异或。
  5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。
  6.重复第2至第5步直到所有数据全部处理完成。
  7.最终CRC寄存器的内容即为CRC值。

二、 循环冗余码校验程序的编写

  明白了CRC校验码的产生过程,编写起程序来就非常容易了。由于Visual Basic的广泛
普及以及其在数据通讯中的重要地位,下面就以VB语言来编写CRC的生成程序,其它语言只
需稍做修改即可。
  编写CRC校验程序有两种办法:一种为计算法,一种为查表法。下面对两种方法分别讨
论。

  1.计算法
  计算法就是依据CRC校验码的产生原理来设计程序。其优点是模块代码少,修改灵活,
可移植性好。其缺点为计算量大。为了便于理解,这里假定了三位数据,而多项式码为
A001(hex)。
  在窗体上放置一命令按钮Command1,并添加如下代码:

  Private Sub Command1_Click()
   Dim CRC() As Byte
   Dim d() As Byte '待传输数据
   ReDim d(2) As Byte
   d(0) = 123
   d(1) = 112
   d(2) = 135
   CRC = CRC16(d) '调用CRC16计算函数
   'CRC(0)为高位
   'CRC(1)为低位
  End Sub
  注意:在数据传输时CRC的低位可能在前,而高位在后。

  Function CRC16(data() As Byte) As String
   Dim CRC16Lo As Byte, CRC16Hi As Byte   'CRC寄存器
   Dim CL As Byte, CH As Byte        '多项式码&amp;HA001
   Dim SaveHi As Byte, SaveLo As Byte
   Dim i As Integer
   Dim Flag As Integer
   CRC16Lo = &amp;HFF
   CRC16Hi = &amp;HFF
   CL = &amp;H1
   CH = &amp;HA0
   For i = 0 To UBound(data)
    CRC16Lo = CRC16Lo Xor data(i) '每一个数据与CRC寄存器进行异或
    For Flag = 0 To 7
     SaveHi = CRC16Hi
     SaveLo = CRC16Lo
     CRC16Hi = CRC16Hi / 2      '高位右移一位
     CRC16Lo = CRC16Lo / 2      '低位右移一位
     If ((SaveHi And &amp;H1) = &amp;H1) Then '如果高位字节最后一位为1
      CRC16Lo = CRC16Lo Or &amp;H80   '则低位字节右移后前面补1
     End If              '否则自动补0
     If ((SaveLo And &amp;H1) = &amp;H1) Then '如果LSB为1,则与多项式码进行异或
      CRC16Hi = CRC16Hi Xor CH
      CRC16Lo = CRC16Lo Xor CL
     End If
    Next Flag
   Next i
   Dim ReturnData(1) As Byte
   ReturnData(0) = CRC16Hi       'CRC高位
   ReturnData(1) = CRC16Lo       'CRC低位
   CRC16 = ReturnData
  End Function

  2.查表法
  查表法的优缺点与计算法的正好相反。为了便于比较,这里所有的假定与计算法的完
全相同,都而在窗体上放置一个Command1的按钮,其代码部分与上面的也完全一致。下面
只介绍CRC函数的编写源代码。

  Private Function CRC16(data() As Byte) As String
   Dim CRC16Hi As Byte
   Dim CRC16Lo As Byte
   CRC16Hi = &amp;HFF
   CRC16Lo = &amp;HFF
   Dim i As Integer
   Dim iIndex As Long
   For i = 0 To UBound(data)
    iIndex = CRC16Lo Xor data(i)
    CRC16Lo = CRC16Hi Xor GetCRCLo(iIndex)    '低位处理
    CRC16Hi = GetCRCHi(iIndex)          '高位处理
   Next i
   Dim ReturnData(1) As Byte
   ReturnData(0) = CRC16Hi    'CRC高位
   ReturnData(1) = CRC16Lo    'CRC低位
   CRC16 = ReturnData
  End Function

  'CRC低位字节值表
  Function GetCRCLo(Ind As Long) As Byte
   GetCRCLo = Choose(Ind + 1, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41,
&amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1,
&amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, &amp;H80, &amp;H41,
&amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1,
&amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40,
&amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0,
&amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, &amp;H80, &amp;H41,
&amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0,
&amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40,
&amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, _
&amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41,
&amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1,
&amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, &amp;H80, &amp;H41,
&amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H0, &amp;HC1,
&amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41,
&amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1,
&amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, &amp;H80, &amp;H41,
&amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H0, &amp;HC1, &amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1,
&amp;H81, &amp;H40, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H1, &amp;HC0, &amp;H80, &amp;H41, &amp;H0, &amp;HC1, &amp;H81, &amp;H40)
  End Function

  'CRC高位字节值表
  Function GetCRCHi(Ind As Long) As Byte
   GetCRCHi = Choose(Ind + 1, &amp;H0, &amp;HC0, &amp;HC1, &amp;H1, &amp;HC3, &amp;H3, &amp;H2, &amp;HC2,
&amp;HC6, &amp;H6, &amp;H7, &amp;HC7, &amp;H5, &amp;HC5, &amp;HC4, &amp;H4, &amp;HCC, &amp;HC, &amp;HD, &amp;HCD, &amp;HF, &amp;HCF,
&amp;HCE, &amp;HE, &amp;HA, &amp;HCA, &amp;HCB, &amp;HB, &amp;HC9, &amp;H9, &amp;H8, &amp;HC8, &amp;HD8, &amp;H18, &amp;H19, &amp;HD9,
&amp;H1B, &amp;HDB, &amp;HDA, &amp;H1A, &amp;H1E, &amp;HDE, &amp;HDF, &amp;H1F, &amp;HDD, &amp;H1D, &amp;H1C, &amp;HDC, &amp;H14,
&amp;HD4, &amp;HD5, &amp;H15, &amp;HD7, &amp;H17, &amp;H16, &amp;HD6, &amp;HD2, &amp;H12, &amp;H13, &amp;HD3, &amp;H11, &amp;HD1,
&amp;HD0, &amp;H10, &amp;HF0, &amp;H30, &amp;H31, &amp;HF1, &amp;H33, &amp;HF3, &amp;HF2, &amp;H32, &amp;H36, &amp;HF6, &amp;HF7,
&amp;H37, &amp;HF5, &amp;H35, &amp;H34, &amp;HF4, &amp;H3C, &amp;HFC, &amp;HFD, &amp;H3D, &amp;HFF, &amp;H3F, &amp;H3E, &amp;HFE,
&amp;HFA, &amp;H3A, &amp;H3B, &amp;HFB, &amp;H39, &amp;HF9, &amp;HF8, &amp;H38, &amp;H28, &amp;HE8, &amp;HE9, &amp;H29, &amp;HEB,
&amp;H2B, &amp;H2A, &amp;HEA, &amp;HEE, &amp;H2E, &amp;H2F, &amp;HEF, &amp;H2D, &amp;HED, &amp;HEC, &amp;H2C, &amp;HE4, &amp;H24,
&amp;H25, &amp;HE5, &amp;H27, &amp;HE7, &amp;HE6, &amp;H26, &amp;H22, &amp;HE2, &amp;HE3, &amp;H23, &amp;HE1, &amp;H21, &amp;H20,
&amp;HE0, &amp;HA0, &amp;H60, _
&amp;H61, &amp;HA1, &amp;H63, &amp;HA3, &amp;HA2, &amp;H62, &amp;H66, &amp;HA6, &amp;HA7, &amp;H67, &amp;HA5, &amp;H65, &amp;H64,
&amp;HA4, &amp;H6C, &amp;HAC, &amp;HAD, &amp;H6D, &amp;HAF, &amp;H6F, &amp;H6E, &amp;HAE, &amp;HAA, &amp;H6A, &amp;H6B, &amp;HAB,
&amp;H69, &amp;HA9, &amp;HA8, &amp;H68, &amp;H78, &amp;HB8, &amp;HB9, &amp;H79, &amp;HBB, &amp;H7B, &amp;H7A, &amp;HBA, &amp;HBE,
&amp;H7E, &amp;H7F, &amp;HBF, &amp;H7D, &amp;HBD, &amp;HBC, &amp;H7C, &amp;HB4, &amp;H74, &amp;H75, &amp;HB5, &amp;H77, &amp;HB7,
&amp;HB6, &amp;H76, &amp;H72, &amp;HB2, &amp;HB3, &amp;H73, &amp;HB1, &amp;H71, &amp;H70, &amp;HB0, &amp;H50, &amp;H90, &amp;H91,
&amp;H51, &amp;H93, &amp;H53, &amp;H52, &amp;H92, &amp;H96, &amp;H56, &amp;H57, &amp;H97, &amp;H55, &amp;H95, &amp;H94, &amp;H54,
&amp;H9C, &amp;H5C, &amp;H5D, &amp;H9D, &amp;H5F, &amp;H9F, &amp;H9E, &amp;H5E, &amp;H5A, &amp;H9A, &amp;H9B, &amp;H5B, &amp;H99,
&amp;H59, &amp;H58, &amp;H98, &amp;H88, &amp;H48, &amp;H49, &amp;H89, &amp;H4B, &amp;H8B, &amp;H8A, &amp;H4A, &amp;H4E, &amp;H8E,
&amp;H8F, &amp;H4F, &amp;H8D, &amp;H4D, &amp;H4C, &amp;H8C, &amp;H44, &amp;H84, &amp;H85, &amp;H45, &amp;H87, &amp;H47, &amp;H46,
&amp;H86, &amp;H82, &amp;H42, &amp;H43, &amp;H83, &amp;H41, &amp;H81, &amp;H80, &amp;H40)
  End Function

  以上程序在Win98,VB6下调试通过。
 
zengxing的答案 感觉不赖
zengxing (2000-5-3 23:56:31)
老兄,是不是做课程设计.:)
CRC校验的原理并不复杂:
CRC码利用N位码,N=K+R,K位数据位,R位校验码
(1)传输前先编码:
将数据位左移R位,相当于乘上2的次方,设C(X)为数据,G(X)为多项式
C(X)*POW(2,R)/G(X)=Q(X)+R(X)/G(X)
Q(X)为商,R(X)/G(X)为余数,
(2) 由于CRC的四则运算采用模2运算,不考虑借位移位.所以有
C(X)*POW(2,R)=Q(X)*G(X)+R(X)
C(X)*POW(2,R)+R(X)=Q(X)*G(X)
注意:R(X)换边,符号不变.
(3)C(X)*POW(2,R)+R(X)即为N位CRC码,R(X)即为校验码,C(X)*POW(2,R)即为
左移R位的数据.
诚然(C(X)*POW(2,R)+R(X))/G(X)=Q(X),余数为0.
校验时将CRC码除以G(X),余数为0则传输数据正确,否则错误,要求重新传输.
(4)常用的CRC编码的G(X)多项式:
一个G(X)多项式对应特定的N,K
N K 多项式 G(X)编码
7 4 X3+X+1 1011
7 4 X3+X2+1 1101
7 3 X4+X3+X+1 11011
7 3 X4+X2+X+1 10111
15 11 X4+X+1 10011
31 26 X5+X2+1 100101
63 57 X6+X+1 1000011
1041 1024 X16+X15+X2+1 1100 0000 0000 0101
(5)模2运算:
就是普通的二进制运算不考虑借位,进位.
+法:0+0=0 , 0+1=1, 1+0=1 , 1+1=0
-法:0-0=0 , 0-1=1, 1-0=0 , 1-1=0
*法:利用模2加法求部分积之和,无进位.
/法:利用模2减法求部分积之和,无借位.
(6)如还有疑问请查阅
1.软件水平考试专用书<<程序设计>>程序员级,高级程序员级 王春森
2.<<计算机组成与结构>> 王爱英
都是清华大学出版社的.

 
酷毕了!
{*********************************************************************}
{ }
{ SelfAV 应用程序病毒免疫控件 }
{ Version 1.23 版本 1.23 }
{ }
{ }
{ CopyRight Jingyu Zhou. 版权:与月共舞工作室 周劲羽 }
{ }
{ 说明:不用编写一行代码,轻松使你的程序具有防病毒校验和被非法修改 }
{ 后自动修复功能的傻瓜式控件,支持多语种、支持压缩工具。 }
{ }
{ 声明:1. 本控件为免费软件,您可以在任何地方使用并遵守以下条款。 }
{ 2. 可免费用于商业用途,但是您不能单独出售本控件或它的源代码。}
{ 3. 您也不能出售利用本控件改写成的控件和源代码。 }
{ 4. 作者不对因使用该控件而造成的任何损失负责。 }
{ 5. 作者保留该控件中由作者编写的代码的所有权利。 }
{ 6. 任何人都可以修改本控件,请您把修改后的源代码寄一份给我。 }
{ 7. 在您的软件中,请保留这段说明。 }
{ 8. 您使用该控件,说明您同意以上条款。 }
{ 9. 您在使用中有任何问题,可与作者联系。 }
{ 10.如果您觉得这个控件对您有帮助,愿意给作者发一封贺卡或邮件,}
{ 作者会非常感激,当然如果您愿意寄钱过来作者也不会反对:) }
{ }
{ Mail:yygw@yeah.net; yygw@sina.com }
{ Homepage:http://yygw.126.com }
{*********************************************************************}


支持平台:
---------
目前已测试通过的平台有:
Win95/98/Me/NT/2000 Professional + Delphi 5.0/6.0

控件说明:
---------
1.控件属性:
AllowCompress 是否支持Aspack等工具对程序进行压缩
AllowRepair 是否允许创建备份文件、允许修复
AutoRepair 是否允许自动提示修复,如果AllowRepair为假,忽略该参数
CompressPos 在被压缩后CRC数据保存的位置(见“注意事项”)
Enabled 是否允许病毒免疫
Language 控件语种(目前支持中文简体、繁体、英文)
可由用户自行扩充
DialogText 对话框显示文本
CanRepair CRC错误且可以自动修复对话框文本
CannotRepair CRC错误但不能自动修复对话框文本
Compress 软件压缩后提示重新免疫对话框文本
Title 对话框标题(通用)
BakFileName 备份文件名(默认为文件名+BK.DAT,可带目录)

2.控件方法:
Check 对系统进行检测并返回结果
Repair 修复系统

3.控件事件:
OnCRCError 系统检测到自身被修改,参数CanRepair表示能否自动修复。如果AllowRepair为假,用户在此增加处理代码。

4.使用方法:
在主窗体上放置一个TSelfAV控件,编译执行即可,程序在脱离IDE环境第一次运行时自动进行免疫。

5.注意事项:
1)如果你选择了允许压缩,请仔细阅读下面的内容:
在压缩前一定要先执行一次应用程序,保证经过了免疫处理。
目前已通过测试的压缩软件有(Windows 98SE + Delphi5.0):
  Aspack V1.061b
Aspack V2.001
Upx V1.07w
PECompact V1.41 UnRegistered
PeX V0.99 by bart
如果压缩、免疫后运行不正常,可能是你使用的压缩软件处理方法不同引起的。你需要手工更改CRC校验值存放的位置:
A.编译、运行、压缩你的软件。
B.用十六进制编辑器打开它,从中找一处没有数据的地址(很长一串0),记下该地址。
C.将控件的CompressPos属性改为这个地址。
D.再次编译、运行、压缩、免疫,如果不出意外的话,应该可以了。
要是还不行,请与我联系!
2)在一些大的软件(特别是带数据库系统)或使用了Flash窗口的软件中,为了使控件能更早的运行,建议将该控件放到工程文件中,如下所示:
文件名:Project1.dpr
program Project1;
uses
Forms,
SelfAV,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}

var
SelfAV1: TSelfAV;
begin
SelfAV1 := TSelfAV.Create(nil);
SelfAV1.AllowCompress := True;
SelfAV1.Check;
SelfAV1.Free;
if Application.Terminated then
Exit;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

更新记录:
---------
2001.08.04 V1.23
新增一个窗体中只允许单控件实例功能
新增DialogText属性,允许直接设计对话框文本
新增CompressPos属性,用于设定压缩参数
新增隐含属性BaseCRC和PosXor(随机数),替代对应的常量

2001.05.10 V1.22
程序在IDE中运行时控件自动失效
只有脱离IDE环境运行才进行免疫和检测
以避免对调试的影响和修正在NT下IDE中运行时的错误
(该功能只在Delphi5中通过测试)

2001.04.14 V1.21
修正控件在WinNT4下不能使用的问题

2001.04.02 V1.2
增加对Aspack、Upx等压缩软件的支持
增加多语种支持(允许用户扩充)
允许用户不创建备份文件、不进行修复
取消了用处不大的参数
优化代码,减少附加的RES文件大小
所有标志数据经过处理,可防止一般的破解

2001.03.25 V1.1
增加自动写校验标志功能
控件升级为全智能傻瓜式

2001.03.23 V1.0
创建控件

特别感谢:
---------
Berl帮我制作多语种支持的英文部分
Lius Pater为这个控件提出建议和帮助测试
还有其它写信支持我、提出意见、帮我测试的热心朋友们


版权所有:
---------
与月共舞工作室 周劲羽
yygw@yeah.net; yygw@sina.com
http://yygw.126.com
OICQ:991144

 
所有的回答我都仔细看过并进行了分析。wys205的答案从程序上看最为清楚,但是缺少原理
的说明,可以说关于查表的原理我现在还是没有彻底看明白;honestman的答案本来有原理
有程序,应该最完美,可惜我对CRC寄存器还不是很了解,始终不明白为什么要向右移位而
不是向左移位:),照单改写后的程序也差距太大。wulianmin的原理阐述也很简洁,只是
没有程序。
其实我很希望能有一段Delphi的程序(计算和查表都有),而且有程序说明,能满足数据串
(而不是单个字符),还是自己动手吧,明白了原理和计算方法应该不算很难,谢谢大家!
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部