2015-10-01 4 views
2

Я портирование следующего кода C из разобранных x86 двоичных:Tricky Целочисленного переполнения при переносе C на C#

(unsigned __int16) ~ (_WORD) crc32^length * ~crc32; 

Это мой перенесенный код в C#:

(uint) (~(ushort) crc32)^length * ~crc32) 

А внизу есть таблица с некоторыми расчетными значениями.

Expected | Actual (C#) 
-----------+------------ 
0x1082B9CB | 0x6082B9CB 
0x30389AF7 | 0x20389AF7 
0xD0EF1CD6 | 0xE0EF1CD6 

Как вы можете видеть, последние три байта верны. Просто первый байт немного сдвинут, но я не вижу никакой картины, как он отличается друг от друга.

Любые идеи, как исправить мой код на C#, чтобы он дал ожидаемый результат?


Примеры значений (С # синтаксис):

uint crc32 = 0x7601A9C5; 
int length = 17; 

Они должны оценивать с 0xD0EF1CD6, но дают 0xE0EF1CD6 вместо этого.


Edit: Я, вероятно, забыл упомянуть важную вещь. Вывод представлен в виде базовых необработанных байтов в шестнадцатеричной нотации.

Рабочий пример кода: https://ideone.com/Z8eONJ

Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(checksum))); 
+2

Можете ли вы привести примеры значений для 'crc32' и' length', которые должны делать ваши ожидаемые значения? – vcsjones

+3

Кажется, что ваши броски назад. '_WORD -> uint',' __int16-> ushort' –

+0

@RobertMcKee: Я думал, что __int16 и ushort равны в C#? Разве это не правда? Я добавил примеры значений, поэтому, если вы считаете, что это помогает, добавьте ответ. – stil

ответ

0

Проблема была с реализацией CRC32. Похоже, что дизассемблированный двоичный файл не отрицал возвращаемого значения, что обычно имеет место в большинстве реализаций CRC32.

public static class Crc32 
{ 
    private static readonly uint[] _table = 
    { 
     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 
     0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 
     ... 
    }; 

    public static uint ComputeChecksum(byte[] bytes) 
    { 
     var crc = 0xffffffff; 
     for (var i = 0; i < bytes.Length; i++) 
     { 
      var t = bytes[i]; 
      var index = (byte) ((crc & 0xff)^t); 
      crc = (crc >> 8)^_table[index]; 
     } 
     return ~crc; // or maybe return crc; 
    } 
} 

Поэтому код:

(uint) (~(ushort) crc32)^length * ~crc32) 

упрощена просто:

(uint) ((ushort) crc32)^length * crc32) 

И теперь он возвращает ожидаемый выход. Мне потребовалось больше времени, чем я согласен признать ...

 Смежные вопросы

  • Нет связанных вопросов^_^