问题
I have been tasked in implementing a Checksum algorithm that is based on the J.G. Fletcher checksum and ISO 8473-1:1998 and is described like so :
They then list 4 data that can be checked to see if the algo is correct but my version fails at the last two values.
0000 gives a checksum of FFFF
0000'00 gives a checksum of FFFF
ABCDEF'01 gives a checksum of 9CF8
1456'F89A'0001 gives a checksum of 24DC
I've been working on this for hours now and can't find what I did wrong, a new set of eyes could help tremendously.
Here is my function:
uint16 Crc_CalculateISOChecksum(uint8 *pt_start_address, uint32 length)
{
uint8 C0, C1;
uint8 data;
uint32 i;
uint8 ck1, ck2;
/* Initial value */
C0 = 0;
C1 = 0;
/* memories - 32bits wide*/
for (i=0; i<length; i++) /* nb_bytes has been verified */
{
data = pt_start_address[i];
C0 = (C0 + data)%255;
C1 = (C1 + C0)%255;
}
/* Calculate the intermediate ISO checksum value */
ck1 = (unsigned char)(255-((C0+C1)%255));
ck2 = (unsigned char)(C1%255);
if (ck1 == 0)
{
ck1 = MASK_BYTE_LSB;
}
if (ck2 == 0)
{
ck2 = MASK_BYTE_LSB;
}
return ((((uint16)ck1)<<8) | ((uint16)ck2));
}
回答1:
Your intermediate sums should be uint16_t (or uint16 in your lingo).
uint16_t C0, C1; // Not uint8_t.
Depending on what char and int on your system are (e.g. do not assume that int has more bits than char) your intermediate sums may be overflowing. Your implementation relies on uint8_t being promoted.
To illustrate:
0xFF 0xFF
+0xFF +0xFF
===== =====
0x1FE % 255 = 0 0xFE % 255 = 254
^Retain ^Drop
回答2:
Just stumbled upon this. If someone is still interested: You iterate in the wrong direction.
Do NOT iterate from 0 to length-1 but from length-1 to 0, then it will work.
for (i = length-1; i >= 0; i--) // and change i to 'signed'
来源:https://stackoverflow.com/questions/8315215/checksum-algorithm-based-on-j-g-fletcher