|
Wil Baden 2001-10-22
The subject of this article is calculation of the International Standard 32-bit CRC, cyclical redundancy check. It uses nonce-words as throw-away definitions to build a table to speed it up.
CRC-32-TableCalculate-CRC-32CRC-32CRC-32-TableCalculate-CRC-32
For testing, Little-Endian-!CRC-TEST
With CRC-32TRUECRC-32Calculate-CRC-32
When CRC-32INVERT
If the CRC is inverted again and added to the end of the file or string in little-endian order, the CRC of the result will be all bits on.
Program Text 1\ The International Standard 32-bit CRC.
CREATE CRC-32-Table 256 CELLS ALLOT
MARKER CRC-32-TABLE-INITIALIZATION
\ Define CRC-POLYNOMIAL from its coefficient terms.
: POLY
32 26 23 22 16 12 11 10 8 7 5 4 2 1 0 ( ...)
0 BEGIN ( ... poly)
SWAP ( ... poly bit)
DUP 32 <>
WHILE
31 XOR 1 SWAP LSHIFT OR ( ... poly)
REPEAT ( ... poly bit)
DROP ( poly)
; POLY CONSTANT CRC-POLYNOMIAL ( )
CR .( \ CRC-POLYNOMIAL is ) CRC-POLYNOMIAL HEX U. DECIMAL CR
CRC-POLYNOMIAL
If you examine the code for Calculate-CRC-for-a-ByteXORCRC-POLYNOMIALCRC-32-TableCRC-POLYNOMIAL
The coefficients of CRC-POLYNOMIAL11 AND1 RSHIFT
After CRC-32-TableCRC-POLYNOMIALCRC-32-Table
: Calculate-CRC-for-a-Byte ( i -- crc )
8 0 DO
dup 1 AND IF
1 RSHIFT CRC-POLYNOMIAL XOR
ELSE
1 RSHIFT
THEN
LOOP ;
: Build-CRC-Table ( -- )
256 0 DO
I Calculate-CRC-for-a-Byte I CELLS CRC-32-Table + !
LOOP ;
Build-CRC-Table
CRC-32-TABLE-INITIALIZATION \ Discard everything after CRC-32-Table.
The print-out has the form it does so you can copy and paste it as the
definition of CRC-32-TableCalculate-CRC-32CRC-32
MARKER ONCE
: Print-CRC-Table
CR ." CREATE CRC-32-Table " CR ." HEX "
256 0 DO
I 4 MOD 0= IF
CR ." ( " I 3 .R ." ) "
THEN
I CELLS CRC-32-Table + @
HEX 0 <# # # # # # # # # #> TYPE ." , " DECIMAL
LOOP
CR ." DECIMAL "
; Print-CRC-Table ONCE
Calculate-CRC-32 ( crc byte -- crc' )
CRC-32 ( crc addr u -- crc' )
: Calculate-CRC-32 ( crc byte -- crc' )
OVER XOR 255 AND CELLS CRC-32-Table + @ SWAP 8 RSHIFT XOR
;
: CRC-32 ( crc addr u -- crc' )
BOUNDS ?DO ( crc) I C@ Calculate-CRC-32 LOOP INVERT ;
Little-Endian-! ( n addr -- )
!CRC-TEST ( str len -- )
: Little-Endian-! ( n addr -- )
4 BOUNDS DO ( n) dup 255 AND I C! 8 RSHIFT LOOP
DROP ;
: CRC-TEST ( str len -- )
dup >R
\ Move string to PAD.
PAD SWAP MOVE ( )
\ Calculate CRC.
TRUE PAD R@ ( crc str len)
CRC-32 ( crc')
\ Show it.
CR ." \ "
dup HEX U. DECIMAL
\ Invert CRC and add to end of string.
INVERT
PAD R@ + Little-Endian-! ( )
\ Check CRC of the result.
TRUE PAD R@ 4 + ( crc str len)
CRC-32 ( crc')
HEX U. DECIMAL ( ) \ Should be all bits on.
R> DROP ;
S" An Arbitrary String" CRC-TEST \ Should be 6FBEAAE7 FFFFFFFF
S" ZYXWVUTSRQPONMLKJIHGFEDBCA" CRC-TEST \ Should be 99CDFDB2 FFFFFFFF
S" 123456789" CRC-TEST \ Should be CBF43926 FFFFFFFF