Основы

Для того чтобы лучше понять суть табличного алгоритма вычисления CRC, обратимся опять к прямому методу, точнее к той схеме его вычисления (см. рис. 9.6), которая была реализована в приведенной выше программе.
Из этой схемы видно, что для текущего содержимого старшей половины регистра ЕАХ можно прогнозировать, как будет изменяться содержимое его битов по мере их сдвига. Для этого достаточно подвергнуть анализу его биты начиная с самого старшего. Допустим, что старшие 8 бит ЕАХ равны а7 а6 а5 а4 а3 а2 а, а,,. При следующем сдвиге (см. рис. 9.6) прямой алгоритм определяет, будет ли произведена операция XOR операнда с полиномом b7 b6 b5 b4 Ь3 b2 b, bо в ВХ (а7=1) или нет (а7=0). Если выдвинутый бит был равен 1, то прежнее содержимое старшей половины регистра ЕАХ будет подвергнуто операции XOR с соответствующими битами полинома. В обратном случае, если выдвинутый бит был равен 0, значения битов будут не изменены, а просто сдвинуты влево на одни разряд. В принципе, имея большое желание, можно рассчитать заранее, каким будет содержимое к-го бита в к-й итерации сдвига. К примеру, значение нового старшего бита, определяющего действия алгоритма в следующей итерации, можно рассчитать по содержимому двух старших битов старшего байта исходного операнда — а6 XOR а7 AND b7, где b7 — старший бит полинома (всегда равный единице).
Теперь остановимся для того, чтобы рассмотреть и обсудить очередную схему (рис. 9.7).

Рис. 9.7. Влияние на регистр ЕАХ серии операций XOR при вычислении CRC

Из рассуждений выше следует, что если взять для рассмотрения старший байт операнда, то по его содержимому можно однозначно предположить, сколько операций XOR и когда будет выполнено (см. рисунок). Обозначим старшую половину регистра ЕАХ как переменную А, а операнды со значениями полинома, объединяемые с А при единичном состоянии очередного выдвигаемого слева бита, обозначим соответственно как В, С, D (помним, что В = С = D). Тогда формирование результата Е можно представить формулой:

Е-((А [сдвиги| XOR В) [сдвигиj XOR С) |сдвиги| XOR D

Здесь | сдвиги | представляют собой значение от 0 до 7 и определяются теку щим содержимым старшего байта операнда (регистра ЕАХ). Благодаря ассоциативному свойству операции XOR тот же самый результат можно получить, если предварительно выполнить операцию XOR над полиномами В, С, D с соответствующими значениями сдвигов, а затем результат объединить по XOR с А:

F: = 1 сдвиги| XOR ( В |сдвиги| XOR С |сдвиги| XOR D) Е:= A XOR F

Из этих рассуждений следуют важные выводы:

  • величина F является совершенно точно предсказуемой по содержимому старшего байта операнда;
  • если величина F определяется содержимым старшего байта операнда и собственно значением полинома, то существует всего 256 возможных значений этой величины (по количеству значений, представимых беззнаковым байтом);
  • исходя из первых двух положений величина F не зависит от значения операнда и может быть рассчитана заранее, при этом результаты ее расчетов можно свести в таблицу (!).

Вот мы и выяснили, на чем основано название табличного алгоритма расчета CRC. Теперь со знанием сути дела приведем его общее описание (рис. 9.8). В качестве основы для рассуждений по-прежнему используем программу прямого вычисления значения CRC и соответствующую схему (см. рис. 9.6).


Рис. 9.8. Общая схема табличного алгоритма

На схеме, показанной на рисунке, цифрами обозначена последовательность шагов табличного алгоритма. Шаги 1 и 2 выполняются одновременно и означают, что старший байт из регистра ЕАХ выдвигается в переменную R, а младший байт этого регистра заполняется очередным байтом исходной последовательности. Значение переменной R используется на шаге 3 в качестве индекса в таблице TABL_F для извлечения 16-битного значения, которое на шаге 4 будет объединено
операцией XOR с содержимым старших 16 битов регистра ЕАХ. Таким образом, в отличие от прямого алгоритма процесс преобразования вырастает до уровня байтов и содержит три операции: сдвига, доступа к таблице для извлечения нужного значения и операции XOR извлеченного значения с содержимым старшей половины ЕАХ. По окончании процесса в старшей половине ЕАХ будет содержаться значение CRC. Сообщение по-прежнему должно быть выровненным, то есть дополненным количеством битов, равным степени полинома, или для данного случая — 16. Для практических приложений это крайне неудобно, и решение этой проблемы будет показано чуть ниже. Пока же разработаем программу вычисления содержимого таблицы на основе полинома 1021h степени 16.

:prg09_03.asm - программа вычисления содержимого таблицы :на основе полинома 1021п степени 16.
.data
tabl_16 dw 256 dup (0) :CRC-таблица
len_tabl_16=$-tabl_16
adr_tabl_16 dd tabl_16
polinom dw 1021h
.code
les di,adr_tabl_16
add di.len_tabl_16-2
std :идем назад по таблице
mov ex.255
mov bx.polinom
ml: xor ax.ax
mov ah.cl :индекс в таблице для вычисления CRC
push ex сложенные циклы
mov ex. 8
m2: shl ax.l
jnc m3 :старшие разряды не равны - выполняем сдвиг
: (частное нас не интересует) ;старшие разряды равны - выполняем XOR:
xor ax.bx :ax XOR polinom
m3: loop m2 _^
pop ex
stosw
loop ml

В результате работы этой программы область памяти tabl_16 будет инициализирована таблицей значений, которые могут быть использованы в схеме вычис-- ления значения CRC исходной последовательности (см. рис. 9.8).

Прямой табличный алгоритм CRC16

'Необходимость дополнения исходной строки завершающими нулевыми байтами представляет большое неудобство при реализации общей схемы табличного
алгоритма. Поэтому на практике используют другую схему вычисления CRC, не требующую завершения исходного сообщения нулевыми байтами. В этой схеме

очередной байт исходной строки объединяется операцией XOR со старшим байтом регистра, выдвинутым с левой стороны этого регистра. Полученное в результате объединения значение используется в качестве индекса для доступа к CRC-таб-лице. Извлекаемое из CRC-таблицы значение объединяется операцией XOR с содержимым регистра. Описанный алгоритм называют прямым табличным алгоритмом.

Рис. 9.9. Схема вычислений CRC с использованием прямого табличного алгоритма

На схеме вычислений CRC с использованием прямого табличного алгоритма цифрами обозначена последовательность шагов вычисления CRC.

  1. 1. Выдвижение старшего байта регистра АХ в байтовую ячейку.
    2. Выполнение операции XOR над выдвинутым на шаге 1 в байтовую ячейку старшим байтом регистра АХ и очередным байтом исходной строки.
    3. Полученное на шаге 2 значение используется в качестве индекса для доступа к элементу CRC-таблицы.
    4. Извлеченное из CRC-таблицы значение объединяется по XOR со значением в регистре АХ.
    5. Результат выполнения на шаге 4 операции XOR помещается обратно в регистр АХ.

После обработки последнего байта исходной строки регистр АХ содержит значение CRC. Программа вычисления CRC с использованием прямого табличного алгоритма приведена ниже.

:prg09_04.asm - программа вычисления CRC с использованием прямого табличного алгоритма.
.......... »
.data
;исходная битовая последовательность в символах
bit_string db "6476c8"
1en_bi t_string=$-bi t_stri ng
adr_bit_string dd bit_string
tabl_16 dw 256 dup (0) iCRC-таблица
Ien_tab1_16=$-tabl_16 adr_tabl_16 dd tabl_16
polinom dw 1021h
.code
.-------------расчитываем CRC-таблицу---.....-------------
les di.adr_tabl_16
add di.len_tabl_16-2
std :идем назад по таблице
mov ex.255
mov bx.polinom
ml: xor ax,ax
mov ah.cl :индекс в таблице для вычисления CRC
push ex сложенные циклы
mov ex.8
m2: shi ax.l
jnc m3 ;старшие разряды не равны - выполняем сдвиг (частное нас не интересует)
:старшие разряды равны - выполняем XOR:
xor ax.bx :ax XOR polinom
тЗ: loop m2
pop ex
stosw
loop ml
-------------закончили расчет CRC-таблицы.........
хог ах,ах
xor bx.bx
Ids si.adrbitstring
mov cx.len_bit_string
m4: mov bl.ah
shl ax.8
xor bl.[si]
xor ax.tabl_16[bx]
inc si
1oop m4
;.........

Рассмотрением этого алгоритма введение в проблему вычисления CRC можно было бы и закончить. Все существующие алгоритмы вычисления CRC являются, по сути, различными модификациями описанного выше табличного алгоритма. Эти модификации преследуют разные цели, перечислим некоторые из них:

  • переход от цикла по всем битам к циклу по большим порциям данных — байтам, словам и т. д.;
  • повышение разрядности порождающего полинома;
  • отражение особенностей функционирования аппаратуры передачи данных (наличие этой цели обусловлено тем, что микросхемы, поддерживающие работу последовательного порта компьютера, передачу байта начинают с его младших битов, поэтому описанные ниже алгоритмы расчета CRC, учитывающие эту особенность, называются зеркальными).

Алгоритмы вычисления CRC получили свое закрепление в некоторых стандартах. Перечислим отличительные особенности основных алгоритмов вычисле-^ ния CRC. Итак, основные алгоритмы вычисления CRC различаются:

  • по значению и степени порождающего полинома, при этом значение полинома обычно указывается без ведущей единицы в старшем разряде;
  • по начальному содержимому регистра, в котором формируется значение CRC;
    по тому, производится ли обращение битов каждого байта перед его обработкой;
  • по способу прохода байтов через регистр — способ может быть косвенным или прямым;
  • по тому, производится ли обращение конечного результата;
  • по конечному значению, с которым производится объединение по XOR результата вычисления CRC.

После появления 32-разрядных микропроцессоров наибольшей популярностью стали пользоваться 32-разрядные алгоритмы вычисления CRC. В различных источниках рассматривают два типа таких алгоритмов — прямой и зеркальный. Рассмотрим их конкретные реализации, рекомендуемые стандартами.