有谁知道这个Delphi CRC16算法有什么问题?

时间:2012-02-14 04:18:57

标签: delphi crc

这是我们公司主要应用程序使用的CRC.dll中的导出函数。我需要在用C#编写的新应用程序中复制它的校验和计算错误,以保持向后兼容性。

这完全超出了我的想象,但我知道Stackoverflow上有很多非常聪明的人,所以我想我会试试运气。它出什么问题了?我怎样才能在C#中复制它?

  CRC_16_TABLE_1 : array[0..255] of Byte =
   (
    $00, $80, $80, $00, $80, $00, $00, $80, $80, $00, $00, $80, $00, $80, $80, $00,
    $80, $00, $00, $80, $00, $80, $80, $00, $00, $80, $80, $00, $80, $00, $00, $80,
    $80, $00, $00, $80, $00, $80, $80, $00, $00, $80, $80, $00, $80, $00, $00, $80,
    $00, $80, $80, $00, $80, $00, $00, $80, $80, $00, $00, $80, $00, $80, $80, $00,
    $81, $01, $01, $81, $01, $81, $81, $01, $01, $81, $81, $01, $81, $01, $01, $81,
    $01, $81, $81, $01, $81, $01, $01, $81, $81, $01, $01, $81, $01, $81, $81, $01,
    $01, $81, $81, $01, $81, $01, $01, $81, $81, $01, $01, $81, $01, $81, $81, $01,
    $81, $01, $01, $81, $01, $81, $81, $01, $01, $81, $81, $01, $81, $01, $01, $81,
    $83, $03, $03, $83, $03, $83, $83, $03, $03, $83, $83, $03, $83, $03, $03, $83,
    $03, $83, $83, $03, $83, $03, $03, $83, $83, $03, $03, $83, $03, $83, $83, $03,
    $03, $83, $83, $03, $83, $03, $03, $83, $83, $03, $03, $83, $03, $83, $83, $03,
    $83, $03, $03, $83, $03, $83, $83, $03, $03, $83, $83, $03, $83, $03, $03, $83,
    $02, $82, $82, $02, $82, $02, $02, $82, $82, $02, $02, $82, $02, $82, $82, $02,
    $82, $02, $02, $82, $02, $82, $82, $02, $02, $82, $82, $02, $82, $02, $02, $82,
    $82, $02, $02, $82, $02, $82, $82, $02, $02, $82, $82, $02, $82, $02, $02, $82,
    $02, $82, $82, $02, $82, $02, $02, $82, $82, $02, $02, $82, $02, $82, $82, $02
   );

  CRC_16_TABLE_2 : array[0..255] of Byte =
   (
    $00, $05, $0f, $0a, $1b, $1e, $14, $11, $33, $36, $3c, $39, $28, $2d, $27, $22,
    $63, $66, $6c, $69, $78, $7d, $77, $72, $50, $55, $5f, $5a, $4b, $4e, $44, $41,
    $c3, $c6, $cc, $c9, $d8, $dd, $d7, $d2, $f0, $f5, $ff, $fa, $eb, $ee, $e4, $e1,
    $a0, $a5, $af, $aa, $bb, $be, $b4, $b1, $93, $96, $9c, $99, $88, $8d, $87, $82,
    $83, $86, $8c, $89, $98, $9d, $97, $92, $b0, $b5, $bf, $ba, $ab, $ae, $a4, $a1,
    $e0, $e5, $ef, $ea, $fb, $fe, $f4, $f1, $d3, $d6, $dc, $d9, $c8, $cd, $c7, $c2,
    $40, $45, $4f, $4a, $5b, $5e, $54, $51, $73, $76, $7c, $79, $68, $6d, $67, $62,
    $23, $26, $2c, $29, $38, $3d, $37, $32, $10, $15, $1f, $1a, $0b, $0e, $04, $01,
    $03, $06, $0c, $09, $18, $1d, $17, $12, $30, $35, $3f, $3a, $2b, $2e, $24, $21,
    $60, $65, $6f, $6a, $7b, $7e, $74, $71, $53, $56, $5c, $59, $48, $4d, $47, $42,
    $c0, $c5, $cf, $ca, $db, $de, $d4, $d1, $f3, $f6, $fc, $f9, $e8, $ed, $e7, $e2,
    $a3, $a6, $ac, $a9, $b8, $bd, $b7, $b2, $90, $95, $9f, $9a, $8b, $8e, $84, $81,
    $80, $85, $8f, $8a, $9b, $9e, $94, $91, $b3, $b6, $bc, $b9, $a8, $ad, $a7, $a2,
    $e3, $e6, $ec, $e9, $f8, $fd, $f7, $f2, $d0, $d5, $df, $da, $cb, $ce, $c4, $c1,
    $43, $46, $4c, $49, $58, $5d, $57, $52, $70, $75, $7f, $7a, $6b, $6e, $64, $61,
    $20, $25, $2f, $2a, $3b, $3e, $34, $31, $13, $16, $1c, $19, $08, $0d, $07, $02
   );

function CRC_16( var buf : array of Byte; Length : Word; Flag : Byte )
         : Word; export;
var
  i          : Word;
  a1, a2, a3 : Byte;
begin
  a1 := 0;
  a2 := 0;
  if (Flag = CRC_MAKE) then
    begin
    buf[Length-2] := 0;
    buf[Length-1] := 0;
    end;
  for i := 0 to Length-1 do
    begin
    a3 := a1;
    a1 := CRC_16_TABLE_1[a3] xor a2;
    a2 := CRC_16_TABLE_2[a3] xor Buf[i];
    end;
  if (Flag = CRC_MAKE) then
    begin
    buf[Length-2] := a1;
    buf[Length-1] := a2;
    end;
  result := a1 * 256 + a2;
end;

2 个答案:

答案 0 :(得分:3)

以下是Delphi代码的C#版本:

static int[] CRC_16_TABLE_1 = {
    0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00,
    0x80, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x80,
    0x80, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x80,
    0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00,
    0x81, 0x01, 0x01, 0x81, 0x01, 0x81, 0x81, 0x01, 0x01, 0x81, 0x81, 0x01, 0x81, 0x01, 0x01, 0x81,
    0x01, 0x81, 0x81, 0x01, 0x81, 0x01, 0x01, 0x81, 0x81, 0x01, 0x01, 0x81, 0x01, 0x81, 0x81, 0x01,
    0x01, 0x81, 0x81, 0x01, 0x81, 0x01, 0x01, 0x81, 0x81, 0x01, 0x01, 0x81, 0x01, 0x81, 0x81, 0x01,
    0x81, 0x01, 0x01, 0x81, 0x01, 0x81, 0x81, 0x01, 0x01, 0x81, 0x81, 0x01, 0x81, 0x01, 0x01, 0x81,
    0x83, 0x03, 0x03, 0x83, 0x03, 0x83, 0x83, 0x03, 0x03, 0x83, 0x83, 0x03, 0x83, 0x03, 0x03, 0x83,
    0x03, 0x83, 0x83, 0x03, 0x83, 0x03, 0x03, 0x83, 0x83, 0x03, 0x03, 0x83, 0x03, 0x83, 0x83, 0x03,
    0x03, 0x83, 0x83, 0x03, 0x83, 0x03, 0x03, 0x83, 0x83, 0x03, 0x03, 0x83, 0x03, 0x83, 0x83, 0x03,
    0x83, 0x03, 0x03, 0x83, 0x03, 0x83, 0x83, 0x03, 0x03, 0x83, 0x83, 0x03, 0x83, 0x03, 0x03, 0x83,
    0x02, 0x82, 0x82, 0x02, 0x82, 0x02, 0x02, 0x82, 0x82, 0x02, 0x02, 0x82, 0x02, 0x82, 0x82, 0x02,
    0x82, 0x02, 0x02, 0x82, 0x02, 0x82, 0x82, 0x02, 0x02, 0x82, 0x82, 0x02, 0x82, 0x02, 0x02, 0x82,
    0x82, 0x02, 0x02, 0x82, 0x02, 0x82, 0x82, 0x02, 0x02, 0x82, 0x82, 0x02, 0x82, 0x02, 0x02, 0x82,
    0x02, 0x82, 0x82, 0x02, 0x82, 0x02, 0x02, 0x82, 0x82, 0x02, 0x02, 0x82, 0x02, 0x82, 0x82, 0x02
};

static int[] CRC_16_TABLE_2 = {
    0x00, 0x05, 0x0f, 0x0a, 0x1b, 0x1e, 0x14, 0x11, 0x33, 0x36, 0x3c, 0x39, 0x28, 0x2d, 0x27, 0x22,
    0x63, 0x66, 0x6c, 0x69, 0x78, 0x7d, 0x77, 0x72, 0x50, 0x55, 0x5f, 0x5a, 0x4b, 0x4e, 0x44, 0x41,
    0xc3, 0xc6, 0xcc, 0xc9, 0xd8, 0xdd, 0xd7, 0xd2, 0xf0, 0xf5, 0xff, 0xfa, 0xeb, 0xee, 0xe4, 0xe1,
    0xa0, 0xa5, 0xaf, 0xaa, 0xbb, 0xbe, 0xb4, 0xb1, 0x93, 0x96, 0x9c, 0x99, 0x88, 0x8d, 0x87, 0x82,
    0x83, 0x86, 0x8c, 0x89, 0x98, 0x9d, 0x97, 0x92, 0xb0, 0xb5, 0xbf, 0xba, 0xab, 0xae, 0xa4, 0xa1,
    0xe0, 0xe5, 0xef, 0xea, 0xfb, 0xfe, 0xf4, 0xf1, 0xd3, 0xd6, 0xdc, 0xd9, 0xc8, 0xcd, 0xc7, 0xc2,
    0x40, 0x45, 0x4f, 0x4a, 0x5b, 0x5e, 0x54, 0x51, 0x73, 0x76, 0x7c, 0x79, 0x68, 0x6d, 0x67, 0x62,
    0x23, 0x26, 0x2c, 0x29, 0x38, 0x3d, 0x37, 0x32, 0x10, 0x15, 0x1f, 0x1a, 0x0b, 0x0e, 0x04, 0x01,
    0x03, 0x06, 0x0c, 0x09, 0x18, 0x1d, 0x17, 0x12, 0x30, 0x35, 0x3f, 0x3a, 0x2b, 0x2e, 0x24, 0x21,
    0x60, 0x65, 0x6f, 0x6a, 0x7b, 0x7e, 0x74, 0x71, 0x53, 0x56, 0x5c, 0x59, 0x48, 0x4d, 0x47, 0x42,
    0xc0, 0xc5, 0xcf, 0xca, 0xdb, 0xde, 0xd4, 0xd1, 0xf3, 0xf6, 0xfc, 0xf9, 0xe8, 0xed, 0xe7, 0xe2,
    0xa3, 0xa6, 0xac, 0xa9, 0xb8, 0xbd, 0xb7, 0xb2, 0x90, 0x95, 0x9f, 0x9a, 0x8b, 0x8e, 0x84, 0x81,
    0x80, 0x85, 0x8f, 0x8a, 0x9b, 0x9e, 0x94, 0x91, 0xb3, 0xb6, 0xbc, 0xb9, 0xa8, 0xad, 0xa7, 0xa2,
    0xe3, 0xe6, 0xec, 0xe9, 0xf8, 0xfd, 0xf7, 0xf2, 0xd0, 0xd5, 0xdf, 0xda, 0xcb, 0xce, 0xc4, 0xc1,
    0x43, 0x46, 0x4c, 0x49, 0x58, 0x5d, 0x57, 0x52, 0x70, 0x75, 0x7f, 0x7a, 0x6b, 0x6e, 0x64, 0x61,
    0x20, 0x25, 0x2f, 0x2a, 0x3b, 0x3e, 0x34, 0x31, 0x13, 0x16, 0x1c, 0x19, 0x08, 0x0d, 0x07, 0x02
};

static int CRC_16(byte[] buf, int length, bool make)
{
    int a1 = 0;
    int a2 = 0;
    if (make)
    {
        buf[length-2] = 0;
        buf[length-1] = 0;
    }
    for (int i=0; i<length; i++)
    {
        int a3 = a1;
        a1 = (CRC_16_TABLE_1[a3] ^ a2) & 0xff;
        a2 = (CRC_16_TABLE_2[a3] ^ buf[i]) & 0xff;
    }
    if (make)
    {
        buf[length-2] = (byte)a1;
        buf[length-1] = (byte)a2;
    }
    return a1*256+a2;
}

我一直使用int来减少需要完成的投射量。

至于你的Delphi代码,我认为你的长度参数只是一个16位整数。我的测试文件大小> 32kb,这让我困惑了一段时间。我还要评论无符号类型不适合循环变量。如果您调用长度为0的函数,则输入i的变量Word将导致AV。当然,buf[Length-1]buf[Length-2]的访问权限是当长度太小时也会出现问题。

答案 1 :(得分:1)

好吧,我不能为你改写这个东西,但它的总体安排非常明显...... Pascal不是那个与其他语言不同!< / p>

试试这个:去互联网找一个已经用C#编写的CRC-16算法。然后,将两个例程的代码并排放置。你正在寻找一个例程,它也有两个固定的常量表,它们也像这个例程那样循环遍历它们,但这是用C#编写的。然后, gosh ...... 那时必要的调整应该是非常明显的,你不觉得吗? (我的意思是,这个东西的整个胆量就像25行一样?): - }