3

我的问题的简短背景: 我正在开发一个小型业余项目,其中的微控制器通过 UART 与 PC 通信。现在我正在使用带有 0x00 数据包分隔符字节和一个简单的 1 字节校验和的 COBS 字节填充,该校验和是二进制补码运行和或一个补码和。我的补码校验和实现与Internet 校验和非常相似(第 7 页。有趣的部分如下所示)

//  Fold 32-bit sum to 16 bits //
while (sum>>16)
    sum = (sum & 0xffff) + (sum >> 16);

checksum = ~sum; 

几天前我发现了关于 Fletcher 校验和:
Fletcher 文章
Fletcher implementation
Fletcher Wikipedia

Fletcher Wiki 页面的短代码片段:

for( index = 0; index < count; ++index )
{
    sum1 = (sum1 + data[index]) % 255;
    sum2 = (sum2 + sum1) % 255;
}

return (sum2 << 8) | sum1;

我的问题:在上面的两篇文章中,他们都说 Fletcher 使用“一个补码 [mod(255)] 校验和”,就好像 mod-255 和一个补码和是相同的。这是真的吗?

  1. 与上面的补码加法器相比,使补码校验和更优越的进位位在 mod-255 和中的工作方式几乎相同,这对我来说是有意义的。但是对于 mod-255 的总和,您永远无法获得值 0xFF (-0),只有 0x00 (+0)?
  2. 我猜 mod-operator 比较慢(虽然它是线性的,所以你可以等待 mod- 计算直到总和结束)。
  3. 一个不错的功能(使用 COBS 时)是 mod-255 永远不会产生 0x00 校验字节,因为 mod-255 的总和永远不会是 0xFF(尽管即使在上面的补码加法器中也很容易修复)。

非常感谢您的参与!

亲切的问候/亨利克

4

1 回答 1

0

不,Modulo 255 不等于 One's Complement。我认为这里的混淆是弗莱彻的校验和同时使用了模 255 加法并将一个的补码作为最后一步。此外,速度慢得多的模运算符可能只是ADC对它可能在 asm 中使用的运算符进行建模。

One's Complement 是位的反转(按位非),通常作为计算的最终操作完成,称为“取一个补码”。这样做是为了优化验证过程并强制正确的结果为 -0(或二进制的 1111 1111)。它仅在使用补码算法的低级硬件上真正有用。现在大多数其他人都使用二进制补码,因此为了达到同样的效果,除了位反转之外,您还必须减去一个。

模 255 是不同的。其意图可能是对“带进位加法”指令进行建模。如果 Fletcher-16 是用 ADC 指令汇编实现的,我不会感到惊讶。

基本上,它不仅仅是忽略溢出,而是在设置时添加进位位。模 255 在这里实现了相同的效果。通常这样做是为了以非常低的成本提高校验和的错误检测质量。

于 2019-12-26T19:42:47.297 回答