这是哪种CRC算法(BBC微型磁带归档系统使用)



这个CRC实现有一个众所周知的名称吗?这个代码是用C编写的,但我认为这与BBC micro的磁带归档系统使用的CRC计算相同。但BBC的微文件并没有具体说明CRC的名称。我也找不到任何明显的匹配http://reveng.sourceforge.net/crc-catalogue/16.htm或https://en.wikipedia.org/wiki/Cyclic_redundancy_check

inline unsigned long crc_cycle(unsigned long crc)
{
if (crc & 32768)
return  (((crc ^ 0x0810) & 32767) << 1) + 1;
else
return crc << 1;
}
unsigned long crc_update(unsigned long crc, const byte *start, const byte *end)
{
for (const byte* p = start; p < end; ++p)
{
crc ^= *p++ << 8;
for(int k = 0; k < 8; k++)
crc = crc_cycle(crc);
assert((crc & ~0xFFFF) == 0);
}
return crc;
}
unsigned long crc(const byte *start, const byte* end)
{
return crc_update(0, start, end);
}

英国广播公司《微型计算机高级用户指南》第348页也描述了这种校验和,但也没有给出名称。该页面上的代码是6502汇编:

LDA #0
STA H  Initialise the CRC to zero
STA L
TAY  Initialise the data pointer
.nbyt LDA H  Work data into CRC
EOR data,Y
STA H
LDX #8  Perform polynomial recycling
.loop LDA H  Loop is performed 8 times, once for bit
ROL A Test if a bit is being cycled out
BCC b7z
LDA H  Yes, add it back in *~8~5
EOR #8
STA H
LDA L
EOR #&l0
STA L
.b7z  ROL L  Always, rotate whole CRC left one bit
ROL H
DEX
BNE loop Do once for each bit
INY Point to next data byte
CPY #lblk All done yet?
BNE nbyt
RTS All done- H=CRC Hi, L=CRC

多项式为0x10000+(0x810<<1(+1=0x1021,称为CRC16-CCITT。

然而,根据我在20世纪80年代和Wiki文章中回忆的内容,CRC16-CCITT是使用多项式0x11021为任何CRC命名的。除了多项式之外,CRC可以是左移(未反映(、右移(反映(,具有初始值,并且结果可以是互补的。在线计算器有相应的复选框:反映输入、反映输出、初始值、最终xor值。(输入和输出的反射不相同的情况很少见(。

该代码实现了一个左移CRC,初始值为0,没有最终的异或,假设没有像CRC_update这样的另一个函数不接受输入参数并将CRC初始化为某个特定值。

Mark Adler指出了代码中的错误,比如在循环中增加p两次。我也看不出断言的意义(crc&~0xffffff==0((~0xffff==0x…0000?(

问题中的C源代码出错。指向数据的指针无意中增加了两次,只对每隔一个字节计算CRC!此:

crc ^= *p++ << 8;

应该是这样的:

crc ^= *p << 8;

汇编程序代码中有一个字符在手册中出现错误,其中EOR #&l0本应为EOR #&10

更正后,两个代码都计算CRC-16/XMODEM

(这里的另一个答案是将"CRC16-CCITT"称为具有该多项式的CRC家族,但reveng目录中的CRC-16/CCITT不会产生与问题中的代码相同的输出。虽然它们使用相同的多项式,但CRC-16/CCITT得到了反映,而代码中的CRC则没有。(

最新更新