Перейти к содержанию
    

Вычисление CRC

Здравствуйте. Буду признателен если спасёте от инвалидности по мозгу.

Среда WinAVR. Вычисляю CRC32 как описано тут http://ru.wikipedia.org/wiki/Crc#CRC-32

// ===================================================
unsigned long CRC32Table[256]  = {0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, итд}
int main(void)
{
  unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  int len = 9;
  volatile long crc = 0xFFFFFFFF;
  while (len--)
  {
    crc = (crc >> 8) ^ (CRC32Table[(crc ^ a[9 - len]) & 0xFF]);
  }
  crc = crc ^ 0xFFFFFFFF;

В результате CRC == 0xE1042295 (Эмуляция в AVR студии)

 

Теперь то же самое на Delphi

// ====================================================
procedure TForm1.Button1Click(Sender: TObject);
const
tbl: array [0..255] of integer = ($00000000, $77073096, $EE0E612C, $990951BA, ...);
arr: array [0..8] of byte = (1,2,3,4,5,6,7,8,9);
var
  crc, len: integer;
begin
  len := 9;
  crc := $FFFFFFFF;
  while len > 0 do begin
    crc := (crc shr 8) xor tbl[(crc xor arr[9 - len]) and $FF];
    Dec(len);
  end;
  crc := crc xor $FFFFFFFF;
  label1.Caption := inttostr(crc);
end;

Здесь CRC = $40EFAB9E;

 

Кто виноват, а главное, что делать.

Забыл сказать - с вероятностью 99,9(9) правильный результат в Delphi т. к.

этот алгоритм был использован в старых проектах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто виноват, а главное, что делать.

Нулевой байт в C-варианте игнорируется, т.к. len на первом проходе уже равна 8. Плюс считается один байт за границами массива a[].

Исправить можно многими способами. Самый простой и корявый - заменить 9 на 8.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разберитесь, когда выполняется декремент len в программе на C и когда в программе на Delphi B)

 

Пока отвечал, Вам уже ответил уважаемый aaarrr.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Косячок подправил но всё равно что то не то

    for (int i = 0; i < 9; i++)
    {
        crc = (crc >> 8) ^ (CRC32Table[(crc ^ a[i]) & 0xFF]);
    }
    crc = crc ^ 0xFFFFFFFF;

Теперь CRC = 0x15E95EF1

p.s. Если глупости спрашиваю прошу прощения, я с С не очень, а WinAVR второй день юзаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В ТОЧКУ!!!!!

volatile unsigned long crc = 0xFFFFFFFF;

aaarrr большое спасибо!!!

Теперь CRC как положено 0x40EFAB9E;

 

Изменено пользователем 6Ф3П

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По поводу volatile совершенно согласен.

Проблема в том что я в студии не могу посмотреть знач. переменной. Объясните пожалуйста в чём дело.

//  ================================================================
long CalculateCRC32Block(unsigned char* buf, unsigned int len)
{
   unsigned long crc = 0xFFFFFFFF;
   while (len--)
   {
        crc = (crc >> 8) ^ pgm_read_dword(&(CRC32Table[(crc ^ *buf++) & 0xFF]));    
   }
   return crc ^ 0xFFFFFFFF;
}

 

Если так

//  ================================================================
int main(void)
{
   unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
   volatile unsigned long crc = CalculateCRC32Block(a, 9);

то значение переменной crc в студии не видно

 

Так тоже не видно

//  ================================================================
int main(void)
{
   unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
   unsigned long crc = 0;
   crc = CalculateCRC32Block(a, 9);

 

И только так я могу его посмотреть

//  ================================================================
int main(void)
{
  unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  volatile unsigned long crc = 0;
  crc = CalculateCRC32Block(a, 9);

 

Может лучше использовать какую-нибудь другую программу для отладки?

Или руки кривые?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

....

Может лучше использовать какую-нибудь другую программу для отладки?

Или руки кривые?

Не надо =)

Всё просто. Скорее всего компилятор разместил переменную crc в регистре. А если переменная в регистре зачастую GNU отладчик её значение получить не может. volatile заставляет компилятор не оптимизировать обращение к crc и как следствие размещает её в доступной отладчику ram.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не надо =)

Всё просто. Скорее всего компилятор разместил переменную crc в регистре. А если переменная в регистре зачастую GNU отладчик её значение получить не может. volatile заставляет компилятор не оптимизировать обращение к crc и как следствие размещает её в доступной отладчику ram.

Ну а map-файл или как он там в GCC называется глянуть можно и ручками посмотреть содержимое нужного

регистра?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ps

Кто виноват, а главное, что делать.

Забыл сказать - с вероятностью 99,9(9) правильный результат в Delphi т. к.

этот алгоритм был использован в старых проектах.

когда сомневаешься - какой алгоритм считает правильно, а какой нет, см он-лайн калькулятор црц http://www.lammertbies.nl/comm/info/crc-calculation.html

 

строка "01 02 03 04 05 06 07 08 09" и тип данных hex. результат: CRC-32 0x40EFAB9E

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...