CRC任意长度数据,任意长度多项式计算。
说明:将待检验数据存入iap中,用strdatasize表示需要计算的数据的字节数;Divisor表示多项式,可以是任意长度字节。
使用方法:首先定义一个package_t类型的变量package。然后直接调用M2stream函数来得到CRC校验码。通过读取package中的元素crc所指向的值来得到CRC校验码。程序带有自检功能,即得到CRC校验码后进行验证。
#include
#include
#include
#include
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
#define u64 unsigned long
/***************************************/
u8 iap[] =
{
0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
0x07,0x06,0x05,0x00,0x03,0x01,0x02,0x03,
0x00,0x01,0x62,0x03,0x04,0x05,0x06,0x07,
0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,0x00
};
/***************************************/
/**/
/*包大小*/
#define strdatasize 64
/*除数*/
const u8 Divisor[] = { 0xf5,0x84,0x26 };
/*人为错误开关*/
#define ErKey 0
/*人为错误索引*/
#define ErIn 4
/*人为错误更改值*/
#define ErVa 0xa8
/*寄存器值打印开关*/
#define RegKey 0
/*检查时被除数流值打印开关*/
#define StrKey 0
/**/
/***************************************/
typedef struct
{
u8 *data;//数据
u32 newdataBnum;//新数据有效字节数
}reg_t;
typedef struct
{
u8 *data;//数据
u8 *datastart;//空间最初位置
u8 *dataend;//数据尾指针
u32 newdataBnum;//新数据有效字节数
u32 newdatabnum;//新数据有效位数
}divisor_t;
typedef struct
{
u8 *stream;//流
u8 *crc;//校验码指针
u8 *streamstart;//流空间最初起始位置
u8 *streamend;//流尾
u32 dednum;//被除数流的有效位数
u32 zeronumstr;//流数据前导零
u32 LMcountadd;//流数据左移总位数 (不包含初始左移)
u32 countover;
reg_t reg; //寄存器
divisor_t divisor;//除数
} package_t;
//计算前导零
u8 ZeroNum(u32 Value)
{
u8 num = 0;
for (;!(Value&(1 << (32 - 1 - num)));num++)
{
if (num >= 32)
{
//printf("大于32\n");
break;
}
}
return num;
}
//获取流数据前导零
u32 ZeroNumStream(u8 *p, u32 num)
{
u32 i = 0;
while (1)
{
if (ZeroNum(p[i]) == 32)i++;
else
return 8 * i + (8 - (32 - ZeroNum(p[i])));
if (i == num)
{
printf("流数据全位0\n");
return num * 8;
}
}
}
/**********************************************************************************************/
//流数据左移函数
u8* ML_stream(u8 *p, u16 size, u16 n)
{
u32 i = n / 8;
u8 j = n % 8;
u32 temp = 0;
p += i;
size -= i;
while (1)
{
p[temp] = p[temp] << j;
if (temp>size)
{
break;
}
if (temp> (8 - j));
}
temp++;
}
return p;
}
//流数据右移函数
u8* MR_stream(u8 *p, u16 size, u16 n)
{
u16 i = n / 8;
u8 j = n % 8;
u16 temp = size - i - 1;
while (1)
{
p[temp] = p[temp] >> j;
if (temp == 0)
{
break;
}
p[temp] |= (p[temp - 1] & (~(0xff << j))) << (8 - j);
temp--;
}
return p;
}
//获取初始寄存器
void GetReg(package_t *Package)
{
u8 i = 0;
Package->reg.newdataBnum = Package->divisor.newdataBnum;//寄存器字节数
Package->reg.data = Package->stream;//寄存器数据指针指向流的开头
#if RegKey
printf("寄存器: ");
for (i = 0;ireg.newdataBnum;i++)
{
printf("%x ", Package->reg.data[i]);
}
printf("\n");
#endif
}
void init_package(package_t *Package)
{
int i = 0;
u8 temp = 0;
/*保证除数不为0*/
for (i = 0;idivisor.datastart=Package->divisor.data = (u8 *)malloc(sizeof(Divisor)); //申请除数空间
Package->divisor.dataend = Package->divisor.data + sizeof(Divisor);
memset(Package->divisor.data, 0, Package->divisor.dataend - Package->divisor.data);//空间清零
memcpy(Package->divisor.data, Divisor, Package->divisor.dataend - Package->divisor.data);//生成初始除数
printf("初始除数: ");
for (i = 0;idivisor.dataend - Package->divisor.data;i++)
{
printf("%x ", Package->divisor.data[i]);
}
printf("\n");
Package->divisor.newdatabnum = (Package->divisor.dataend - Package->divisor.data) * 8 - ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data);
Package->divisor.data = ML_stream(Package->divisor.data, Package->divisor.dataend- Package->divisor.data, ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data));
//Package->divisor.newdataBnum = (Package->divisor.newdatabnum + 8 - 1) / 8;
Package->divisor.newdataBnum = Package->divisor.dataend - Package->divisor.data;
printf("除数有效位数:%d", Package->divisor.newdatabnum);
printf("\n");
printf("有效除数: ");
for (i = 0;idivisor.dataend - Package->divisor.data;i++)
{
printf("%x ", Package->divisor.data[i]);
}
printf("\n");
/*获取被除数流相关数据*/
Package->streamstart=Package->stream = (u8 *)malloc(strdatasize + Package->divisor.newdataBnum); //申请被除数流空间
Package->streamend = Package->stream + strdatasize + Package->divisor.newdataBnum;
memset(Package->stream, 0, Package->streamend- Package->stream);//空间清零
memcpy(Package->stream, iap, strdatasize);//生成初始被除数流
printf("初始被除数流: ");
temp = 0;
for (i = 0;istreamend - Package->stream;i++)
{
printf("%x ", Package->stream[i]);
temp |= Package->stream[i];
}
printf("\n");
if (!temp)
{
printf("被除数除数不能为0\n");
exit(-1);
}
Package->zeronumstr = ZeroNumStream(Package->stream, Package->streamend - Package->stream);//获取流数据前导零
printf("流数据前导零:%d\n", Package->zeronumstr);
Package->dednum = strdatasize * 8 - Package->zeronumstr + Package->divisor.newdatabnum - 1;//被除数流有效位数
Package->LMcountadd = 0;//初始化流数据左移总位数值
printf("被除数流有效位数:%d\n", Package->dednum);
Package->stream = ML_stream(Package->stream, Package->streamend - Package->stream, Package->zeronumstr);//左移获得有效初始流数据
/*获取初始寄存器相关数据*/
GetReg(Package);
/*申请CRC校验值空间*/
Package->crc = (u8 *)malloc(Package->reg.newdataBnum); //申请CRC校验值空间
printf("初始化完成\n");
}
#if 1
void init_package_check(package_t *Package)
{
u32 i = 0;
u8 temp = 0;
/*保证除数不为0*/
for (i = 0;idivisor.data = Package->divisor.datastart; //指回初始地址
Package->divisor.dataend = Package->divisor.data + sizeof(Divisor);
memset(Package->divisor.data, 0, Package->divisor.dataend - Package->divisor.data);//空间清零
memcpy(Package->divisor.data, Divisor, Package->divisor.dataend - Package->divisor.data);//生成初始除数
printf("初始除数: ");
for (i = 0;idivisor.dataend - Package->divisor.data;i++)
{
printf("%x ", Package->divisor.data[i]);
}
printf("\n");
Package->divisor.newdatabnum = (Package->divisor.dataend - Package->divisor.data) * 8 - ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data);
Package->divisor.data = ML_stream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data, ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data));
//Package->divisor.newdataBnum = (Package->divisor.newdatabnum + 8 - 1) / 8;
Package->divisor.newdataBnum = Package->divisor.dataend - Package->divisor.data;
printf("除数有效位数:%d", Package->divisor.newdatabnum);
printf("\n");
printf("有效除数: ");
for (i = 0;idivisor.dataend - Package->divisor.data;i++)
{
printf("%x ", Package->divisor.data[i]);
}
printf("\n");
/*获取被除数流相关数据*/
Package->stream = Package->streamstart; //
Package->streamend = Package->stream + strdatasize + Package->divisor.newdataBnum;
memset(Package->stream, 0, Package->streamend - Package->stream);//空间清零
memcpy(Package->stream, iap, strdatasize);//生成初始被除数流
for (i = 0;ireg.newdataBnum;i++)
{
Package->stream[strdatasize + i] = Package->crc[i];//将CRC校验值写入被除数流
}
printf("被除数流: ");
for (i = 0;istreamend - Package->stream;i++)
{
printf("%x ", Package->stream[i]);
}
printf("\n");
Package->zeronumstr = ZeroNumStream(Package->stream, Package->streamend - Package->stream);//获取流数据前导零
printf("流数据前导零:%d\n", Package->zeronumstr);
Package->dednum = strdatasize * 8 - Package->zeronumstr + Package->divisor.newdatabnum - 1;//被除数流有效位数
Package->LMcountadd = 0;//初始化流数据左移总位数值
printf("被除数流有效位数:%d\n", Package->dednum);
Package->stream = ML_stream(Package->stream, Package->streamend - Package->stream, Package->zeronumstr);//左移获得有效初始流数据
/*获取初始寄存器相关数据*/
GetReg(Package);
}
u8 check(u8 *p, u16 size)
{
u32 i = 0;
u8 temp = 0;
for (i = 0;istream[ErIn] = ErVa;//制造人为错误
#endif
printf("开始验证-->\n");
while (1)
{
//异或运算
for (i = 0;ireg.newdataBnum;i++)
{
Package->reg.data[i] ^= Package->divisor.data[i];
}
#if StrKey
printf("被除数流数据为: ");
for (i = 0;istreamend - Package->stream;i++)
{
printf("%x ", Package->stream[i]);
}
printf("\n");
#endif
if (check(Package->stream, Package->streamend - Package->stream) == 0)
{
printf("LMcountadd=%d\n", Package->LMcountadd - Package->zeronumstr);
break;
}
else if (Package->LMcountadd>Package->dednum)
{
printf("检查失败:左移次数过大\n");
exit(1);
}
//Sleep(500);
//左移
Package->zeronumstr = ZeroNumStream(Package->stream, strdatasize + sizeof(Divisor));//获取流数据前导零
Package->stream=ML_stream(Package->stream, strdatasize + sizeof(Divisor), Package->zeronumstr);
Package->LMcountadd += Package->zeronumstr;
//更新寄存器
GetReg(Package);
}
printf("检查成功\n");
return 1;
}
#endif
//模2除法针对于流数据
u8 M2stream(package_t *Package)
{
int i = 0;
init_package(Package);//初始化结构体变量
printf("被除数流: ");
for (i = 0;istreamend - Package->stream;i++)
{
printf("%x ", Package->stream[i]);
}
printf("\n");
while (1)
{
//异或运算
for (i = 0;ireg.newdataBnum;i++)
{
Package->reg.data[i] ^= Package->divisor.data[i];
}
#if StrKey
printf("被除数流数据为(%d): ", Package->streamend - Package->stream);
for (i = 0;istreamend - Package->stream;i++)
{
printf("%x ", Package->stream[i]);
}
printf("\n");
#endif
//左移
Package->zeronumstr = ZeroNumStream(Package->stream, Package->streamend - Package->stream);//获取流数据前导零
Package->stream=ML_stream(Package->stream, Package->streamend - Package->stream, Package->zeronumstr);
Package->LMcountadd += Package->zeronumstr;
//更新寄存器
GetReg(Package);
//检查是否操作完成
if (Package->LMcountadd >= Package->dednum - Package->divisor.newdatabnum + 1)
{
i = (Package->dednum - Package->divisor.newdatabnum + 1) - (Package->LMcountadd - Package->zeronumstr);//非校验值位数-该次左移前的总前导零=还需计算的位数
printf("i=%d\n", i);
printf("前导零:%d\n", Package->zeronumstr);
if (Package->zeronumstr - i > Package->reg.newdataBnum)
{
Package->reg.data = MR_stream(Package->reg.data, Package->reg.newdataBnum, Package->reg.newdataBnum);
}
else
{
Package->reg.data = MR_stream(Package->reg.data, Package->reg.newdataBnum, Package->zeronumstr - i);//因为实际上计算到极限并且左移所以需要右移超出本该计算的位数
}
printf("校验码: ");
for (i = 0;ireg.newdataBnum;i++)
{
printf("%x ", Package->reg.data[i]);
}
printf("\n");
Package->countover = Package->LMcountadd - Package->zeronumstr;
printf("countover=%d\n", Package->countover);
//保存CRC校验值
memset(Package->crc, 0, Package->reg.newdataBnum);//空间清零
memcpy(Package->crc, Package->reg.data, Package->reg.newdataBnum);//保存CRC校验值
break;
}
}
if (M2streamCheck(Package))
return 1;//返回包含校验码的数据
else
return 0;
}
int main()
{
package_t package;
M2stream(&package);
return 0;
}