Converting a checksum algorithm from Python to C - c

There is a checksum algorithm for the networks in some Honda vehicles that computes an integer between 0-15 for the provided data. I'm trying to convert it to plain C, but I think I'm missing something, as I get different results in my implementation.
While the Python algorithm computes 6 for "ABC", mine computes -10, which is weird. Am I messing something up with the bit shifting?
The Python algorithm:
def can_cksum(mm):
s = 0
for c in mm:
c = ord(c)
s += (c>>4)
s += c & 0xF
s = 8-s
s %= 0x10
return s
My version, in C:
int can_cksum(unsigned char * data, unsigned int len) {
int result = 0;
for (int i = 0; i < len; i++) {
result += data[i] >> 4;
result += data[i] & 0xF;
}
result = 8 - result;
result %= 0x10;
return result;
}

No, the problem is the modulus. Python follows the sign of the right operand, and C follows the sign of the left. Mask with 0x0f instead to avoid this.
result = 8 - result;
result &= 0x0f;

Related

Calculating checksum (16 bit) in c

I am being asked to do a checksum on this text with the bit size being 16:
"AAAAAAAAAA\nX"
At first the description seemed like it wanted the Fletcher-16 checksum. But the output of Fletcher's checksum performed on the above text yielded 8aee in hex. The example file says that the modular sum algorithm (minus the two's complement) should output 509d in hex.
The only other info is the standard "every two characters should be added to the checksum."
Besides using the generic Fletcher-16 checksum provided on the corresponding Wikipedia page, I have tried using this solution found here: calculating-a-16-bit-checksum to no avail. This code produced the hex value of 4f27.
Simply adding the data seeing it as an array of big-endian 16-bit integers produced the result 509d.
#include <stdio.h>
int main(void) {
char data[] = "AAAAAAAAAA\nX";
int sum = 0;
int i;
for(i = 0; data[i] != '\0' && data[i + 1] != '\0'; i += 2) {
int value = ((unsigned char)data[i] << 8) | (unsigned char)data[i + 1];
sum = (sum + value) & 0xffff;
}
printf("%04x\n", sum);
return 0;
}

Using Bitwise Operators to get Bit Values in C

I am writing a program in C where I am comparing two bytes of data, and then seeing if the bytes are different, and if so, at which bits.
This is what I have so far:
int var1 = 81; //Binary: 0101 0001
int var2 = 193; //Binary: 1100 0001
int diff = var1 ^ var2; //diff = 1001 0000 / 144
Basically I know how to use the XOR bitwise operator to see which bits are different between the two variables, but from here I don't know how to use diff to figure out which bits are the differences. For example, in my above code I'd want to use diff to output "Bit 5 and Bit 8 are different".
You can use a for loop to get that idea and make bitwise AND with 1 properly left shifted to get the set bits positions
for(size_t i = 0; i < sizeof(int)*8; i++){
if( diff & (1U << i))
printf("%zu is different\n",i+1);
}
Far easier to start with unsigned types when doing bit manipulations.
As #coderredoc inquired about solutions across various platforms, even uncommon ones:
Using int:
When int diff is negative, conversion to an unsigned (via masking with an unsigned) may change its bit pattern.
An int may have more than 8 bits per "byte". Diminishes correctness of sizeof(int)*8.
Various integer types may have padding (rare). Diminishes correctness of sizeof(int)*CHAR_BIT.
// OP wants to report first bit index as 1. 0 is more common.
#define BIT_REPORT_OFFSET 0
int bit_position = 0;
int mask;
do {
mask = 1 << bit_position;
if (diff & mask) {
printf("Bit %d\n", bit_position + BIT_REPORT_OFFSET);
}
bit_position++;
} while (mask < INT_MAX/2);
if (diff < 0) {
printf("Bit %d\n", bit_position + BIT_REPORT_OFFSET);
}
For maximum portability, avoid changing types, changing the value of diff and use constants from <limits.h> rather than compute them.
use unsigned int instead of int; then you can use
for (unsigned int pos = 0; diff; ++pos) {
if (diff & 1)
printf("difference in pos %u\n", pos);
diff >>= 1;
}
or
while (diff) {
int pos = ffs(diff);
printf("difference in pos %d\n", pos);
diff &= ~(1u << pos);
}
To get the different bits position, lets say you have 4 byte integer
for(int bit_index = sizeof(diff) - 1; bit_index >= 0;bit_index-- ) {
if((diff >> bit_index & 1) == 1 ){ /* if particular bit is 1, that bit_index value you can use */
printf("[%d] bit is different or 1 \n",bit_index);
}

CRC check XOR Function return value is always 0

I am writing a code to calculate a CRC16 using 32 bit unsigned integers. When trying to print the return value out from the XOR function that performs the CRC operation it always prints 0. I've tried a variety of debug methods such as print statements, however, I can't seem to figure it out!
Here's my XOR function:
uint32_t XOR(uint32_t divisor, uint32_t dividend)
{
uint32_t divRemainder = dividend;
uint32_t currentBit;
for(currentBit = 32; currentBit > 0; --currentBit)
{
if(dividend && 0x32)
{
divRemainder = divRemainder ^ divisor;
}
divRemainder = divRemainder << 1;
}
return (divRemainder >> 8);
}
The function that calls the above method:
void crcCalculation(char *text, FILE *input, char *POLYNOMIAL)
{
int i = strlen(text);
uint32_t dividend = atoi(POLYNOMIAL);
uint32_t result;
readInput(text, input);
printText(text);
printf("CRC 16 calculation progress:\n");
if(i < 504)
{
for(; i!=504; i++)
{
text[i] = '.';
}
}
result = XOR((uintptr_t)POLYNOMIAL, dividend);
printf(" - %d", result);
}
The constant polynomial (I hope I calculated this correctly for CRC 16:
#define POLYNOMIAL A053
I'd appreciate a nudge in the correct direction!
The code if(dividend && 0x32) makes no sense at all and will evaluate to 1. This is the reason why nothing works.
Perhaps you meant if(dividend & 32) or similar? As in bitwise AND instead of logical AND. And hex 0x20 decimal 32 (which could make sense... probably not?) instead of hex 0x32 decimal 50 (which doesn't make any sense at all).
Overall this CRC algorithm looks very fishy. You only iterate over 31 bits, for example.

Fastest way to calculate possible values of unsigned int with N unreliable bits?

Given an unsigned int A (32 bit), and another unsigned int B, where B's binary form denotes the 10 "least reliable" bits of A, what is the fastest way to expand all 1024 potential values of A? I'm looking to do this in C.
E.g uint B is guaranteed to always have 10 1's and 22 0's in it's binary form (10 least reliable bits).
For example, let's say
A = 2323409845
B = 1145324694
Their binary representations are:
a=10001010011111000110101110110101
b=01000100010001000100010010010110
B denotes the 10 least reliable bits of A. So each bit that is set to 1 in B denotes an unreliable bit in A.
I would like to calculate all 1024 possible values created by toggling any of those 10 bits in A.
No guarantees that this is certifiably "the fastest", but this is what I'd do. First, sieve out the fixed bits:
uint32_t const reliable_mask = ~B;
uint32_t const reliable_value = A & reliable_mask;
Now I'd preprocess an array of 1024 possible values of the unreliable bits:
uint32_t const unreliables[1024] = /* ... */
And finally I'd just OR all those together:
for (size_t i = 0; i != 1024; ++i)
{
uint32_t const val = reliable_value | unreliables[i];
}
To get the unreliable bits, you could just loop over [0, 1024) (maybe even inside the existing loop) and "spread" the bits out to the requisite positions.
You can iterate through the 1024 different settings of the bits in b like so:
unsigned long b = 1145324694;
unsigned long c;
c = 0;
do {
printf("%#.8lx\n", c & b);
c = (c | ~b) + 1;
} while (c);
To use these to modify a you can just use XOR:
unsigned long a = 2323409845;
unsigned long b = 1145324694;
unsigned long c;
c = 0;
do {
printf("%#.8lx\n", a ^ (c & b));
c = (c | ~b) + 1;
} while (c);
This method has the advantages that you don't need to precalculate any tables, and you don't need to hardcode the 1024 - it will loop based entirely on the number of 1 bits in b.
It's also a relatively simple matter to parallelise this algorithm using integer vector instructions.
This follows essentially the technique used by Kerrek, but fleshes out the difficult parts:
int* getValues(int value, int unreliable_bits)
{
int unreliables[10];
int *values = malloc(1024 * sizeof(int));
int i = 0;
int mask;
The function definition and some variable declarations. Here, value is your A and unreliable_bits is your B.
value &= ~unreliable_bits;
Mask out the unreliable bits to ensure that ORing an integer containing some unreliable bits and value will yield what we want.
for(mask = 1;i < 10;mask <<= 1)
{
if(mask & unreliable_bits)
unreliables[i++] = mask;
}
Here, we get each unreliable bit into an individual int for use later.
for(i = 0;i < 1024;i++)
{
int some_unreliables = 0;
int j;
for(j = 0;j < 10;j++)
{
if(i & (1 << j))
some_unreliables |= unreliables[j];
}
values[i] = value | some_unreliables;
}
The meat of the function. The outer loop is over each of the outputs we want. Then, we use the lowest 10 bits of the loop variable i to determine whether to turn on each unreliable bit, using the fact that the integers 0 to 1023 go through all possibilities of the lowest 10 bits.
return values;
}
Finally, return the array we built. Here is a short main that can be used to test it with the values for A and B given in your question:
int main()
{
int *values = getValues(0x8A7C6BB5, 0x44444496);
int i;
for(i = 0;i < 1024;i++)
printf("%X\n", values[i]);
}

What's up with this reversing bit order function?

I'm rather ashamed to admit that I don't know as much about bits and bit manipulation as I probably should. I tried to fix that this weekend by writing some 'reverse the order of bits' and 'count the ON bits' functions. I took an example from here but when I implemented it as below, I found I had to be looping while < 29. If I loop while < 32 (as in the example) Then when I try to print the integer (using a printBits function i've written) I seem to be missing the first 3 bits. This makes no sense to me, can someone help me out?
Thanks for everyone's help, I've added comments to show changes I've made.
int reverse(int n)
{
int r = 0;
int i = 0;
for(i = 0; i < 29; i++) //Should be i < 32
{
r = (r << 1) + (n & 1); //| instead of + to make it obvious I'm handling bits
n >>=1;
}
return r;
}
Here is my printBits function:
void printBits(int n)
{
int mask = 0X10000000; //unsigned int mask = 0X80000000;
while (mask)
{
if (mask & n)
{
printf("1");
}
else
{
printf("0");
}
mask >>= 1;
}
printf("\n");
}
And a working? reverse function
int reverse2(int n)
{
int r = n;
int s = sizeof(n) * 7; // int s = (sizeof(n) * 8) -1
for (n >>= 1; n; n >>=1)
{
r <<=1;
r |= n & 1;
s--;
r <<= s;
return r;
}
int mask = 0X10000000;
puts a 1 in bit 28. You want 0X80000000.
You have:
int mask = 0x10000000;
There are two problems here. You don't have the high bit set, and if you did, it still (probably) wouldn't work, as your compiler would be using arithmetic shift on a signed int.
You want to change your mask to:
unsigned int mask = 0x80000000;
For arithmetic shift, shifting 0x80000000 right will never become zero, as the sign bit will be magically extended into the other bits. See here for more details on arithmetic shift.
Print Bits is wrong, its 0x80000000 not 0x10000000.
>>> bin (0x80000000)
'0b10000000000000000000000000000000'
>>> bin (0x10000000)
'0b10000000000000000000000000000'
See 0x1... doesnt set the highest bit.
Instead of +, you should use | (bitwise or). And you should use < 32.
As written, this will reverse the lower 29 bits of n into r. The top three bits of n will be left in n (shifted down 29 bits) and not returned.
I would suspect a problem with your printBits function if you see something else.
edit
Your printBits function prints the lower 29 bits of n, so it all makes sense.

Resources