В чем отличие программной реализации алгоритма CRC от аппаратной?

Тема в разделе "WASM.CRYPTO", создана пользователем AndreyMust19, 19 ноя 2009.

  1. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    Старший бит должен быть всегда 1, иначе при первой же операции получим 1 в остатке и никуда с места не сдвинемся.

    Исходная последовательность.
    010100111010

    Но поскольку она начинается с нуля, двигаем ее влево до первой единицы. Вычисление происходит так (на примере 4-битного):
    10100111010
    1001
    ----
    001101
    1001
    0100
    ----
    1001
    1001
    ----
    00001010
    1001
    ----
    0011

    После каждого XOR остаток сдвигается влево на количество нулей (чтобы первой была 1) и такое же кол-во бит их потока запихивается в конец остатка.

    Но посмотрел алгоритм в Википедии:

    unsigned char Crc8(unsigned char *pcBlock, unsigned char len)
    {
    unsigned char crc = 0xFF;
    unsigned char i;

    while (len--)
    {
    crc ^= *pcBlock++;

    for (i = 0; i < 8; i++)
    crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
    }

    return crc;
    }

    Подсчет crc ведется побайтово (crc ^= *pcBlock++), а не побитово и когда остаток сдвигается, в его конец ничего не пихается (crc << 1). Я понимаю что у ЭВМ нет таких операций как "первые N бит слова запихать в конец другого слова" и не может работать с битами в отдельности.
    Но этот алгоритм встречается везде, скорее всего - он правильный. Тогда я не понимаю - какая хитрость или извращение используется в этом алгоритме. Он другой, но он делает тоже самое. Кто-нибудь может мне объяснить? Советчики не копаться в алгоритме, если все и так работает, пусть читают другую тему.
     
  2. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    Программный делает тоже самое, но с таблицей, обрабатывая сразу 8 бит, усек?
    А вот сама таблица считается побитово, во как.
     
  3. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    На 99% он правильный.

    Но если взять код CRC16-CCITT И проверить прямой метод с побитовым делением и табличный то получаться расхождения. Правда табличный легко корректируется.
     
  4. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    Pavia
    Это еще как??? Примеры в студию!
    А то это типа "как складывать парашют. издание второе, исправленное".
     
  5. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    Наконец-то я смог зайти на сайт. Модем опять его не видит!
    Pavia
    Не факт, есть бестабличные алгоритмы. И для CRC32 и CRC64 таблица будет очень большая.
    Вообще-то CRC - это побитовый алгоритм и почему его используют в ЭВМ, мне непонятно. Алгоритм какой-то извращенный. Но вот скажите, почему делается вот так:
    Код (Text):
    1. crc ^= *pcBlock++;
    Вообщем как побитовый алгоритм заменяется побайтовым и при этом работает одинаково?
    Вот давно я написал тот же алгоритм CRC, но с Init=00h, он побитовый - создается слово, а биты задвигаются в старший байт из младшего, потом когда 8 бит будет задвинуто, в low пихается следующий байт (см. функцию myCrc8):
    http://exfile.ru/68332
    Только вот я не проверил - выдает ли он тот же результат, что и алгоритм, приведенный выше (init разный).
     
  6. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    AndreyMust19
    А почитать? crc
    Смотрим вконце на ссылки. Например: "CRC, и как его восстановить"

    З.Ы Гугл не стоит игнорить.
     
  7. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    Booster
    А почитать первый пост? Цитата:
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    AndreyMust19
    Плохо смотрел.
     
  9. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    AndreyMust19
    В общем, брателло, развел ты здесь настояший детский сад с сопельками и памперсами. Но ничего, обижаться не стоит, тебе тут все объяснят.

    Для начала забудь про побитовое деление и попробуй отыскать остаток от деления обычных чисел, не используя само деление.

    Например, 12345432100 mod 13 = 1

    Составь таблицу остатков, аналогичную той, что используется в CRC:
    Tab[0]=000 mod 13=00
    Tab[1]=100 mod 13=09
    Tab[2]=200 mod 13=05
    Tab[3]=300 mod 13=01
    Tab[4]=400 mod 13=10
    Tab[5]=500 mod 13=06
    Tab[6]=600 mod 13=02
    Tab[7]=700 mod 13=11
    Tab[8]=800 mod 13=07
    Tab[9]=900 mod 13=03

    А теперь откусываем слева первую цифру, находим соответствующей ей остаток из таблицы и прибавляем его с головы:

    12345432100
    3245432100
    255432100
    60432100
    632100
    34100
    4200
    300
    01

    Таким образом, остаток от деления, он же контрольная сумма, равен 1.
    Его мы нашли с помошью поциферной таблицы не прибегая к делению.

    CRC32 и CRC64 работают похожим образом. Таблицы там разумеется небольшие, на 256 входов, всего по числу вариантов значений одного байта (а у нас в примере было 10 входов, так как пример в десятичной системе)

    На практике к последовательности сначала добавляют FFFFFFFF…, чтобы контрольные суммы часто встречающихся последовательностей из нулей были разные. Саму контрольную сумму в конце гасят FFFFFFFF…, чтобы контрольная сумма пустой строки была равна нулю.
     
  10. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    Совсем запутался... То что ты привел из Вики это побитовый алгоритм.
    Побайтовый вот:

    crc=(crc shr 8) xor Table[crc xor byte and 255]
    Для crc8 все вырождается в простую выборку из таблицы
    crc8=Table[crc8 xor byte]

    Такие командочки есть, можешь сдвигать длинные регистры и последовательности. Но с таблицей оно быстрее будет на порядок.
     
  11. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    Ну да, алгоритм побитовый, но организован так, чтобы не двигать каждый раз всю последовательность, а двигать только байт. Настоящие же побайтовые а не эта демострашка дурацкая используют байтовую таблицу.

    Да в том, что аппаратно это происходит в специальном регистре с обратными связями такт за тактом, а не в простом регистре с кучей операций.
     
  12. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    AndreyMust19
    фу ты черт, я и сам запутался где побитовый а где побайтовый. То что ты привел, это действительно побайтовый алгоритм и все что я писал про табличный, к нему применимо.
    Просто код содержит тупую работу и дрючит каждый байт восемь раз вместо того чтобы затабличить один раз и потом вынимать. То есть твой код эквивалентен коду
    crc8=Table[crc8 XOR byte] только таблица каждый раз вычисляется налету, что не целесообразно
     
  13. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    persicum
    В аппаратуре - побитовый, а в системе - программый. Реализации разные, а работать должны одинаково. Вот я и пытаюсь понять - как изменили побайтовый алгоритм, чтобы он работал также, как побитовый.
    Из всего сказанного (спасибо!) я думаю что Википедиа-алгоритм делает так:
    byte ^ 1001101 ^ 0011010 ^ 0110100
    то есть ксорит байт, сдвигает остаток влево, опять ксорит полиномом и так далее 8 раз, то есть цикл "for-8" вычисляет остаток от деления 8-ми битов байта на полином. Как бы не по одному биту за раз, а по 8.

    Решил проверить оба алгоритма, должны выдать одинаковый результат, но не выдают:
    Начальные данные:
    init = 11111111
    poly = 10110001

    MyCrc8:
    Код (Text):
    1. 1101001000111000
    2. xor            |
    3. 11111111       |
    4. --------(180d) |
    5. 00101101       |
    6.   10110100     |
    7.   10110001     |
    8.   --------     |
    9.   0000010111100|(188d)
    10.        10110001|
    11.        --------\
    12.        000011010 = 1Ah
    Crc8:
    Код (Text):
    1. 1101001000111000
    2. xor
    3. 11111111
    4. --------
    5. 00101101
    6.  
    7. Первый байт:
    8. 00101101
    9. <<2 (i = 6)
    10. 101101000 (180d)
    11.  10110001
    12.  --------
    13.  110110010
    14. (i = 4)
    15.   10110001
    16.   --------
    17.   00000011
    18. <<4 (i = 0)
    19.   00110000 (48d)
    20.  
    21. Второй байт:
    22. 00111000
    23. 00101101
    24. --------
    25. 00001000 (8d)
    26. <<4 (i = 4)
    27. 100000000
    28.  10110001 (177d)
    29.  --------
    30.  101100010
    31.   10110001
    32.   --------
    33.   110100110
    34.    10110001
    35.    --------
    36.    00010111 (23d)
    37. <<1 (i = 0)
    38.    00101110 = 2Eh
     
  14. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    AndreyMust19
    пора бы научиться прогать на сях или на пасе...
    Привожу байтовый и битовый релиз crc8, на первый взгляд они ничем не отличаются, но между ними принципиальная разница, попробуй определить какая.

    Код (Text):
    1. {$APPTYPE CONSOLE}
    2.  
    3. type TByte=array [1..MaxInt] of byte;
    4.      PByte=^TByte;
    5.  
    6. var Buff:PByte;
    7.     BuffLen,i:Cardinal;
    8.     crc8:byte;
    9.  
    10. const Poly:byte=$31;
    11.  
    12. //побайтовый алгоритм, xor Poly это сложение
    13. //границы между байтами не обрабатываются
    14. procedure crc8byte(var crc:byte;Buff:PByte;Len:Cardinal);
    15. var i,j:Cardinal;
    16. begin
    17.  for i:=1 to Len do begin
    18.   crc:=crc xor Buff[i];
    19.   for j:=1 to 8 do begin
    20.    if (crc and $80)<>0 then
    21.     crc:=(crc shl 1) xor Poly
    22.    else
    23.     crc:=(crc shl 1);
    24.   end;
    25.  end;
    26. end;
    27.  
    28.  
    29. //побитовый алгоритм, xor Poly это вычитание
    30. //границы между байтами обрабатываются, т.к. сдвигается тип word
    31. procedure crc8bit(var crc:byte;Buff:PByte;Len:Cardinal);
    32. var i,j:Cardinal;
    33.     w,p:word;
    34. begin
    35.  w:=crc shl 8;
    36.  p:=Poly shl 8;
    37.  
    38.  for i:=1 to Len+1 do begin
    39.   if i<=Len then w:=w or Buff[i];
    40.   for j:=1 to 8 do begin
    41.    if (w and $8000)<>0 then
    42.     w:=(w shl 1) xor p
    43.    else
    44.     w:=(w shl 1);
    45.   end;
    46.  end;
    47.  
    48.  crc:=w shr 8;
    49. end;
    50.  
    51. BEGIN
    52.  BuffLen:=2048;
    53.  GetMem(Buff,BuffLen);
    54.  Randomize;
    55.  for i:=1 to BuffLen do Buff[i]:=Random(256);
    56.  crc8:=0;
    57.  crc8byte(crc8,Buff,BuffLen);
    58.  writeln(crc8);
    59.  crc8:=0;
    60.  crc8bit(crc8,Buff,BuffLen);
    61.  writeln(crc8);
    62.  FreeMem(Buff);
    63. END.
     
  15. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    так ты че, серьезно полагаешь что на компе нельзя организовать побитовое деление длинного полинома? Посмотри функцию crc8bit и можешь смело встречать девятнадцатилетие.
     
  16. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    Код (Text):
    1. procedure crc8bit(var crc:byte;Buff:PByte;Len:Cardinal);
    2. var i,j:Cardinal;
    3.     w,p:word;
    4. begin
    5.  w:=crc shl 8;
    6.  p:=Poly shl 8;
    7.  
    8.  for i:=1 to Len+1 do begin
    9.   if i<=Len then w:=w or Buff[i];
    10.   for j:=1 to 8 do begin
    11.    if (w and $8000)<>0 then
    12.     w:=(w shl 1) xor p
    13.    else
    14.     w:=(w shl 1);
    15.   end;
    16.  end;
    17.  
    18.  crc:=w shr 8;
    19. end;
    А разве я выше не тот же алгоритм побитового CRC привел?

    Можно, но процессору проще с байтами работать, чем с битами, поэтому в ЭВМ и используются byte / word / dword. С битами будет менее читаемо и медленнее работать.
     
  17. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    к сожалению, из того что я писал ты ничего не понял. Обрати внимание как ведут себя границы между байтами, где XOR а где OR. Первая процедура считает дискретно байтами, вторая непрерывно, хотя и подгружает тоже байтами.
     
  18. persicum

    persicum New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2007
    Сообщения:
    947
    AndreyMust19
    подсказка: crc8byte это алгоритм из Вики, записанный на пасе, а crc8bit это якобы программно нереализуемый "аппаратный" вариант
     
  19. int_13h

    int_13h New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2008
    Сообщения:
    163
    Адрес:
    Красноряск
    .. в аппаратуре это про контроллеры штоль?.. хм я CRC16 табличный писал для ATmega162/PIC18/8051, вроде как то работает с байтами :lol: