4

I have this function in C that I need to port to C#. I've made a few attempts but can't figure out what I'm doing wrong.

The polynomial is 0x04C11DB7uL.

It doesn't have to include a while loop, i've also attempted with a For loop.

static uint32_t APPL_CalcCRC32(uint32_t u32Sum, uint8_t *pData, uint32_t count)
{

    uint8_t iCounter;
    uint32_t u32Word;
    uint64_t u64Sum;

    u64Sum = u32Sum;

    count = count / 4;  // number of bytes --> number of words

    // algorithm according to AN4187 (Figure 2)
    while (count--)
    {
        u32Word = *((uint32_t*)pData)++;

        u64Sum ^= u32Word;

        for (iCounter = 0; iCounter < (8 * 4); ++iCounter)
        {
            u64Sum <<= 1;

            if (u64Sum & 0x100000000)
            {
                u64Sum ^= 0x04C11DB7uL;
            }
        }
    }

    return (uint32_t)u64Sum;
}

This is my attempt:

private uint CalculateBlockCheckSum( uint u32Sum, byte[] blockImage )
        {
            uint u32Word;
            ulong u64Sum = u32Sum;
            ulong comparisonValue = 0x100000000;
            int count = blockImage.Length / 4;
            int i = 0;
            while ( count-- >= 0 )
            {

                u32Word = blockImage[i++];
                u64Sum ^= u32Word;

                for ( byte iCounter = 0; iCounter < ( 8 * 4 ); ++iCounter )
                {
                    u64Sum <<= 1;

                    if ( ( u64Sum & comparisonValue ) != 0 )
                    {
                        u64Sum ^= 0x04C11DB7uL;
                    }
                }
            }
            return (uint)u64Sum;
        }

My main doubts are the u32Word assignment in my C# function and the loop criteria, are those right?

My test setup are 58 arrays (blocks) with each block 1024 bytes each. But the output of both functions is not the same. So is my function wrong or it is something else?

Ribeiro
  • 364
  • 1
  • 3
  • 12
  • 3
    Could you provide some *test examples*, please? – Dmitry Bychenko Nov 06 '19 at 13:07
  • 4
    Wouldn't it be easier to just look at a specification and reeimplement it without looking at the C code? – klutt Nov 06 '19 at 13:08
  • 4
    I might be wrong, but `while (count--)` in C should be `while (count-- > 0)` in c#, instead of `while (count-- >= 0)` – Cid Nov 06 '19 at 13:08
  • 8
    The C code line `u32Word = *((uint32_t*)pData)++;` re-interprets the `uint8_t *pData` as a `uint32_t *`, so it takes 4 bytes each. This probably depends on the byte order of the system and may require correct alignment of the data. I guess in C# you would have to combine 4 subsequent bytes to a 32-bit unsigned integer. The C implementation seems to require that `count` is a multiple of 4. – Bodo Nov 06 '19 at 13:14
  • @Cid you are absolutely right on that one. Using the equals ended up in an exception. – Ribeiro Nov 06 '19 at 15:03
  • @Bodo absolutely. the accepted answer has this considered with the line: ```u32Word = BitConverter.ToUInt32(blockImage,i*sizeof(uint));``` – Ribeiro Nov 06 '19 at 15:04
  • Following up on @Bodo's comment, if this is a little endian processor, such as X86, then it's not a proper CRC since it's effectively reversing the order of every 4 byte group. – rcgldr Nov 06 '19 at 15:41

1 Answers1

5

You only have to change the line when you move in the next value of you block of data:

private uint CalculateBlockCheckSum(uint u32Sum, byte[] blockImage)
{
    uint u32Word;
    ulong u64Sum = u32Sum;
    ulong comparisonValue = 0x100000000;
    int count = blockImage.Length / sizeof(uint);
    int i = 0;
    while (count-- > 0)
    {
        u32Word = BitConverter.ToUInt32(blockImage,i*sizeof(uint));
        u64Sum ^= u32Word;

        for (byte iCounter = 0; iCounter < (8 * 4); ++iCounter)
        {
            u64Sum <<= 1;

            if ((u64Sum & comparisonValue) != 0)
            {
                u64Sum ^= 0x04C11DB7uL;
            }
        }
        i++;
    }
    return (uint)u64Sum;
}
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
hiral2
  • 194
  • 1
  • 5