개발유틸리티

CRC 의 이해와 계산방법

EP 기술연구소 2012. 3. 20. 12:30

통신을 할 때, 데이터가 수신이 완전히 이루어 졌는가? 에러는 없는가? 는 중요한 요소이다. 이것을 하는 방법은 다양하게 개발 되었다.

- Parity bit     : UART  - 한비트의 데이터로 1의 갯수가 짝수인가 홀수인가를 나타낸다.
- check-sum : CPU 실행 파일의 포맷 - 모든 데이터를 더하여 보수를 취하면 된다.
- CRC          : 가장 안전하게 체크할 수 있지만 복잡하다. 다양한 비트수가 있다.


http://ko.wikipedia.org/wiki/%EC%88%9C%ED%99%98_%EC%A4%91%EB%B3%B5_%EA%B2%80%EC%82%AC


다항식의 종류



여기에 표시하지는 않았지만 더 많은 CRC 종류들이 있다.

  • 적어도 다섯 종류의 서로 다른 CRC-16, CRC-32, CRC-64가 존재하고 널리 사용된다.
  • CRC-64, CRC-128, CRC-256도 존재하고 표준화되어 있지만 널리 사용되지는 않는다.

다음은 ITU-IEEE 문법으로 쓴 다양한 CRC 다항식들이다.

CRC-1 x + 1 (하드웨어에서 사용되며 패리티 비트로 알려져 있음)
CRC-5 x5 + x2 + 1 (USB 토큰 패킷에서 사용됨)
CRC-7 x7 + x3 + 1 (몇몇 통신 체계에서 사용됨)
CRC-8-Fletcher A := A + D[i], B := B + A
CRC-8 x8 + x2 + x + 1
CRC-12 x12 + x11 + x3 + x2 + x + 1 (통신 체계에서 사용됨)
CRC-16-Fletcher (CRC-16 Adler의 기반)
CRC-16-Adler_A [A = 1 + D1 + D2 + ... + Dn (mod 65521)]
CRC-16-Adler_B [B = n×D1 + (n-1)×D2 + (n-2)×D3 + ... + Dn + n (mod 65521)]
CRC-16-CCITT x16 + x12 + x5 + 1
CRC-16-IBM x16 + x15 + x2 + 1
CRC-32-Adler [Adler-32(D) = B × 65536 + A]
CRC-32-IEEE 802.3 x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
CRC-32C (Castagnoli) x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1
CRC-64-ISO x64 + x4 + x3 + x + 1 (ISO 3309)
CRC-64-ECMA-182 x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 + x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 + x10 + x9 + x7 + x4 + x + 1 (ECMA-182 p.63)
CRC-128 (IEEE? / ITU?)

 

 

CRC의 하드웨어 적용과 비교

 

CRC의 다항식으로 부터 논리회로를 만들면 쉬게 CRC 데이터를 만들 수 있다. 그러나 이 경우 시리얼 데이터일 때 회로가 간단하다. 네트워크의 시리얼 전송을 많이 사용하므로 쉽게 논리회로 적용이 가능하다. 그러나 데이터를 처리할 때 프로그램 영역에서는 보통 8, 16,32 비트 등의 여러 비트를 한번에 처리 해야 한다. 따라서 CRC가 시리얼로 올 때 각 클럭의 데이터 계산할 때와는 다르다. 하드웨어 방식을 소프트웨어에서 사용하려면 계산이 많아 진다. 바이트 단위를 비트 단위로 여러번 연산을 해야 하기 때문이다. 이런 문제를 해결하는 것이 CRC 테이블을 이용하는 방법을 많이 사용 한다. 메모리가 많은 경우가 대부분이므로 미리 CRC을 계산하여 놓고 각 비트 단위로 따라가면 된다. 8비트라면 현재 값에서 다음값으로 테이블 이전만 하면 되는 것이다. 따라서 시리얼 계산에 들어가는 시간보다 훨씬 빠른 방법이 된다. 어떤 CRC 상황에서 다음에 오는 한바이트가 오는 경우의 수는 256가지 밖에는 없다. 따라서 256개 중에 하나로 값이 결정되는 것이다. 256의 경우수 만을 가지고 찾기만 하면 되지만 이 경우 1바이트 단위로 찾아간다. 만약 32비트를 한번에 찾으려면 경우의 수가 2^32이므로 테이블의 어래이가 너무 커져 보통 이런경우는 사용하지 않는다.

 

 

CRC-Table과 생성함수와의 관계

 

CRC table 다항식이 결정되면 같은 값이 나온다. 따라서 원하는 다항식에서 부터 table값을 만들어 사용 한다.

 

만드는 방법은 

1. 프로그램 시작하면서 생성함수를 실행하여 RAM의 변수영역에 CRC 데이터를 만든다.

2. 다른 OS나 환경에서 C프로그램으로 table을 만들어 코드를 원하는 프로그램 소스에 추가 한다. 

    이 경우는 CRC table이 이미 생성되어 있기 때문에 생성 함수는 타겟 프로그램에는 필요 없어 진다. 

 

아래의 CRC table C소스를 프로젝트에 추가하여 수신 처리에서 CRC을 계산하는데 사용하면 된다.

 

각 다항식과 비트수에 따른 생성 함수 및 table 소스들이다. 주의 할점은 같은 비트라고 다항식이 틀리면 다른 테이블 값이 나오므로 적용하려는 방정식을 확인 해야 한다. 즉, 방정식이 같은면 다음 예의 테이블 값을 그대로 복사해서 적용하면 된다. 경우에 따라 표준화 되어 있는 몇가지 방정식은 이미 방정식 까지 표준화 되었음을 이해 해야 한다. 특히 네트워크 관련 CRC는 그렇다.

 

 
1.  CRC-8


x8 + x2 + x + 1

static byte crctable[256] = {
    0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
    0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
    0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
    0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
    0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
    0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
    0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
    0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
    0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
    0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
    0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
    0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
    0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
    0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
    0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
    0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
    0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
    0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
    0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
    0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
    0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
    0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
    0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
    0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
    0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
    0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
    0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
    0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
    0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
    0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
    0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
    0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
};

========== table 생성 ===============

static byte crctable[256];

/*
   Generate a table for a byte-wise 8-bit CRC calculation on the polynomial:
   x^8 + x^2 + x^1 + x^0
*/

void make_crc_table( void ) {
    int i, j;
    unsigned long poly, c;
    /* terms of polynomial defining this crc (except x^8): */
    static const byte p[] = {0,1,2};

    /* make exclusive-or pattern from polynomial (0x07) */
    poly = 0L;
    for ( i = 0; i < sizeof( p ) / sizeof( byte ); i++ ) {
        poly |= 1L << p[i];
    }

    for ( i = 0; i < 256; i++ ) {
        c = i;
        for ( j = 0; j < 8; j++ ) {
            c = ( c & 0x80 ) ? poly ^ ( c << 1 ) : ( c << 1 );
        }
        crctable[i] = (byte) c;
    }
}

========== 사용하기 ===============

#define CRC8_INIT_VALUE        0x0000
#define CRC8_XOR_VALUE        0x0000

void CRC8_InitChecksum( unsigned char &crcvalue ) {
    crcvalue = CRC8_INIT_VALUE;
}

void CRC8_Update( unsigned char &crcvalue, const byte data ) {
    crcvalue = crctable[crcvalue ^ data];
}

void CRC8_UpdateChecksum( unsigned char &crcvalue, const void *data, int length ) {
    unsigned char crc;
    const unsigned char *buf = (const unsigned char *) data;

    crc = crcvalue;
    while( length-- ) {
        crc = crctable[crc ^ *buf++];
    }
    crcvalue = crc;
}

void CRC8_FinishChecksum( unsigned char &crcvalue ) {
    crcvalue ^= CRC8_XOR_VALUE;
}

unsigned char CRC8_BlockChecksum( const void *data, int length ) {
    unsigned char crc;

    CRC8_InitChecksum( crc );
    CRC8_UpdateChecksum( crc, data, length );
    CRC8_FinishChecksum( crc );
    return crc;
}

=================================================================================================================

x8x5 + x4 + 1



이것처럼 계산을 하면 되는데 이를 어떻게 고속으로 계산 하라. 비트 단위로 오는 하드웨어에서나 하는거지...

미리 계산하여 테이블을 만들고 바로 찾아가면 8비트 단위로 나온다. 고속으로

CRC-8  Table

const char  tableCRC_8[]  = {
  0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 67, 114, 33, 16,
  135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, 134, 183, 228, 213, 66, 115, 32, 17,
  63, 14, 93, 108, 251, 202, 153, 168, 197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47,
  184, 137, 218, 235, 61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19,
  126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, 187, 138, 217, 232,
  127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 248, 201, 154, 171, 60, 13, 94, 111,
  65, 112, 35, 18, 133, 180, 231, 214, 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144,
  7, 54, 101, 84, 57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23,
  252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, 191, 142, 221, 236,
  123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, 71, 118, 37, 20, 131, 178, 225, 208,
  254, 207, 156, 173, 58, 11, 88, 105, 4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238,
  121, 72, 27, 42, 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239,
  130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172
};

이것을 바로 프로그램에 복사하여 사용하면 된다.


2.  CRC-16

CRC-16   CCITT

x16 + x12 + x5 + 1


#define CRC16_INIT_VALUE    0xffff
#define CRC16_XOR_VALUE        0x0000


============ 만들기  ==========================
static unsigned short crctable[256];

/*
   Generate a table for a byte-wise 16-bit CRC calculation on the polynomial:
   x^16 + x^12 + x^5 + x^0
*/

void make_crc_table( void ) {
    int i, j;
    unsigned long poly, c;
    /* terms of polynomial defining this crc (except x^16): */
    static const byte p[] = {0,5,12};

    /* make exclusive-or pattern from polynomial (0x1021) */
    poly = 0L;
    for ( i = 0; i < sizeof( p ) / sizeof( byte ); i++ ) {
        poly |= 1L << p[i];
    }

    for ( i = 0; i < 256; i++ ) {
        c = i << 8;
        for ( j = 0; j < 8; j++ ) {
            c = ( c & 0x8000 ) ? poly ^ ( c << 1 ) : ( c << 1 );
        }
        crctable[i] = (unsigned short) c;
    }
}


/*
  Table of CRC-16's of all single-byte values (made by make_crc_table)
*/
static unsigned short crctable[256] = {
    0x0000,    0x1021,    0x2042,    0x3063,    0x4084,    0x50a5,    0x60c6,    0x70e7,
    0x8108,    0x9129,    0xa14a,    0xb16b,    0xc18c,    0xd1ad,    0xe1ce,    0xf1ef,
    0x1231,    0x0210,    0x3273,    0x2252,    0x52b5,    0x4294,    0x72f7,    0x62d6,
    0x9339,    0x8318,    0xb37b,    0xa35a,    0xd3bd,    0xc39c,    0xf3ff,    0xe3de,
    0x2462,    0x3443,    0x0420,    0x1401,    0x64e6,    0x74c7,    0x44a4,    0x5485,
    0xa56a,    0xb54b,    0x8528,    0x9509,    0xe5ee,    0xf5cf,    0xc5ac,    0xd58d,
    0x3653,    0x2672,    0x1611,    0x0630,    0x76d7,    0x66f6,    0x5695,    0x46b4,
    0xb75b,    0xa77a,    0x9719,    0x8738,    0xf7df,    0xe7fe,    0xd79d,    0xc7bc,
    0x48c4,    0x58e5,    0x6886,    0x78a7,    0x0840,    0x1861,    0x2802,    0x3823,
    0xc9cc,    0xd9ed,    0xe98e,    0xf9af,    0x8948,    0x9969,    0xa90a,    0xb92b,
    0x5af5,    0x4ad4,    0x7ab7,    0x6a96,    0x1a71,    0x0a50,    0x3a33,    0x2a12,
    0xdbfd,    0xcbdc,    0xfbbf,    0xeb9e,    0x9b79,    0x8b58,    0xbb3b,    0xab1a,
    0x6ca6,    0x7c87,    0x4ce4,    0x5cc5,    0x2c22,    0x3c03,    0x0c60,    0x1c41,
    0xedae,    0xfd8f,    0xcdec,    0xddcd,    0xad2a,    0xbd0b,    0x8d68,    0x9d49,
    0x7e97,    0x6eb6,    0x5ed5,    0x4ef4,    0x3e13,    0x2e32,    0x1e51,    0x0e70,
    0xff9f,    0xefbe,    0xdfdd,    0xcffc,    0xbf1b,    0xaf3a,    0x9f59,    0x8f78,
    0x9188,    0x81a9,    0xb1ca,    0xa1eb,    0xd10c,    0xc12d,    0xf14e,    0xe16f,
    0x1080,    0x00a1,    0x30c2,    0x20e3,    0x5004,    0x4025,    0x7046,    0x6067,
    0x83b9,    0x9398,    0xa3fb,    0xb3da,    0xc33d,    0xd31c,    0xe37f,    0xf35e,
    0x02b1,    0x1290,    0x22f3,    0x32d2,    0x4235,    0x5214,    0x6277,    0x7256,
    0xb5ea,    0xa5cb,    0x95a8,    0x8589,    0xf56e,    0xe54f,    0xd52c,    0xc50d,
    0x34e2,    0x24c3,    0x14a0,    0x0481,    0x7466,    0x6447,    0x5424,    0x4405,
    0xa7db,    0xb7fa,    0x8799,    0x97b8,    0xe75f,    0xf77e,    0xc71d,    0xd73c,
    0x26d3,    0x36f2,    0x0691,    0x16b0,    0x6657,    0x7676,    0x4615,    0x5634,
    0xd94c,    0xc96d,    0xf90e,    0xe92f,    0x99c8,    0x89e9,    0xb98a,    0xa9ab,
    0x5844,    0x4865,    0x7806,    0x6827,    0x18c0,    0x08e1,    0x3882,    0x28a3,
    0xcb7d,    0xdb5c,    0xeb3f,    0xfb1e,    0x8bf9,    0x9bd8,    0xabbb,    0xbb9a,
    0x4a75,    0x5a54,    0x6a37,    0x7a16,    0x0af1,    0x1ad0,    0x2ab3,    0x3a92,
    0xfd2e,    0xed0f,    0xdd6c,    0xcd4d,    0xbdaa,    0xad8b,    0x9de8,    0x8dc9,
    0x7c26,    0x6c07,    0x5c64,    0x4c45,    0x3ca2,    0x2c83,    0x1ce0,    0x0cc1,
    0xef1f,    0xff3e,    0xcf5d,    0xdf7c,    0xaf9b,    0xbfba,    0x8fd9,    0x9ff8,
    0x6e17,    0x7e36,    0x4e55,    0x5e74,    0x2e93,    0x3eb2,    0x0ed1,    0x1ef0
};


3.  CRC-32

이것은 이미 사용한 예시 프로그램이 있고, 첨부 파일을 참고하면 된다.

C 언어의 문자형 변수 char



crc32.cpp - CRC을 만든다.

(1) main() 함수의 초기에 테이블을 만든다.

#define k_poly            ((unsigned int)(0xedb88320))
#define k_crc_table_size    (256)

unsigned int gg_a_crc_table[k_crc_table_size];


char g_comBuff[1024];

typedef unsigned int u32;
typedef struct {
     u32  crc;
     u32  type;
     u32  dlength;
     u32  data[1024];
     // . . .    
} ;

int main(int argc, char* argv[])
{
   int cnt;

    fn_init_crc_table(); // CRC32 초기화 - CRC Table 작성

   makePacket( (PacketStruct *) g_comBuff, (void *) "hello", (int) 6); // 패킷을 만든다.

   send(g_comBuff);

   // . . .
}

void
fn_init_crc_table()
{
    short    i_table;
   
    for (i_table = 0; i_table < k_crc_table_size; i_table++)
    {
        unsigned int    result = 0;
        short    i_bit;
       
        for (i_bit = 0; i_bit < 8; i_bit++)
        {
            unsigned int    bit = ((i_table  & (1 << i_bit)) != 0);
           
            if ((bit ^ (result & 1)) != 0)
                result = (result >> 1) ^ k_poly;
            else
                result >>= 1;
        }
       
        gg_a_crc_table[i_table] = result;
    }
   
} /* end of fn_init_crc_table */

(2) 테이블을 이용하여 패킷을 만들 때, 데이터로 부터 계산 한다.

통신패킷 설정 :

PacketStruct *makePacket(PacketStruct *pkt, void *data, int leng)
{
     unsigned int  datalength;
  
     // 데이터 포멧하기
     pkt->dlength = leng;
     memcpy((void*) &pkg->data, data,leng);
     pkt->type= 0x00100020;

     datalength =  sizeof (PacketStruct) - sizeof(u32);
     unsigned short int rcrc = (u32) fn_calc_memory_crc32( (void *) &pkt->type, datalength);
     pkt->crc = rcrc;
     return pkt;
}


unsigned int
fn_calc_memory_crc32(void *p, unsigned int n_bytes)
{
    fnm_assert_stmt(n_bytes > 4);
   
    return(fn_calc_memory_chunk_crc32(p, n_bytes, k_initial_crc_value));
   
} /* end of fn_calc_memory_crc32 */

static unsigned int
fn_calc_memory_chunk_crc32(void *p, unsigned int n_bytes, unsigned int crc)
{
    unsigned char    *p_uc   = (unsigned char*)p;
    unsigned int   result  = ~crc;
   
    while (n_bytes-- > 0)
    {
        result = (result >> 8) ^ gg_a_crc_table[(result ^ *p_uc++) & 0xff];
    }
   
    return(~result);
   
} /* end of fn_calc_memory_chunk_crc32 */

==============================================================================

CRC-32     IEEE-802.3

x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1

 


 

#define CRC32_INIT_VALUE 0xffffffffL
#define CRC32_XOR_VALUE 0xffffffffL

static unsigned long crctable[256];

/*
Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0.

Polynomials over GF(2) are represented in binary, one bit per coefficient,
with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
byte 0xb1 is the polynomial x^7+x^3+x^1+x^0), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.

This calculation is done using the shift-register method of multiplying and
taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
x^32 mod p is p+x^32 = x^26+...+x^0), and the register is multiplied mod p by
x (which is shifting right by one and adding x^32 mod p if the bit shifted
out is a one). We start with the highest power (least significant bit) of
q and repeat for all eight bits of q.

The table is simply the CRC of all possible eight bit values. This is all
the information needed to generate CRC's on data a byte at a time for all
combinations of CRC register values and incoming bytes.
*/


void make_crc_table( void ) {
int i, j;
unsigned long c, poly;
/* terms of polynomial defining this crc (except x^32): */
static const byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};

/* make exclusive-or pattern from polynomial (0xedb88320L) */
poly = 0L;
for ( i = 0; i < sizeof( p ) / sizeof( byte ); i++ ) {
poly |= 1L << ( 31 - p[i] );
}

for ( i = 0; i < 256; i++ ) {
c = (unsigned long)i;
for ( j = 0; j < 8; j++ ) {
c = ( c & 1 ) ? poly ^ ( c >> 1 ) : ( c >> 1 );
}
crctable[i] = c;
}


 

/*
Table of CRC-32's of all single-byte values (made by make_crc_table)
*/

static unsigned long crctable[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
};



출처] http://blog.naver.com/dolicom