Search code examples
javascriptbit-manipulationbufferchecksum

Why my two's complement gives me a completely different result in javascript


I'm currently figuring out a checksum of a byte buffer of 32 bits each byte, I have to calculate two checksums, 32bit unint sum and 32 bit uint xor for every component of the byte buffer (except some locations). The sum works as expected but the xor gives me a weird value. The value I get from the xor is -58679487 and when applying two's complement I get 58679487 but when converting it to a hex value it is 0x037F60BF and I'm looking for 0xFC809F41. If I place the initial xor value (-58679487) in rapidtables and convert it from dec to hex it displays the correct two's complement value in hex. What am I doing wrong?

i=startAddress;
    while(i<buf.length){
        if(i !== chk1 && i!== chk2 && i!== chk3 && i!== chk4){
            file32Sumt += buf.readUint32BE(i);
            file32Xort ^= buf.readUint32BE(i);
                    i+=4;
            }else{
                console.log('cks location.'+ buf.readUint32BE(i).toString(16));
                i+=4;
                }
         }
//two's complement
console.log((~file32Sumt+1).toString(16));
console.log((~file32Xort+1).toString(16));

Already did the two's complement by using the bitwise NOT operator (~) then adding 1 but seems it's not working. Also tried using Math.abs(file32Xort) but got the same result.


Solution

  • Don't negate. Use this:

    console.log((file32Xort >>> 0).toString(16));
    

    file32Xort has the right value already, but as a signed 32-bit integer. What you need here is the unsigned interpretation of the same value. number >>> 0 is a simple way to do that reinterpretation.

    Additionally, I think you should write

    file32Sumt = (file32Sumt + buf.readUint32BE(i)) >>> 0;
    

    .. or something to that effect, this time using some bitwise operator (it doesn't have to be an unsigned right shift, but I think that makes sense in this context) to prevent the sum from becoming too large (by limiting it to 32 bits) and potentially exhibiting floating point rounding. The calculation of file32Xort already uses a bitwise operator so it doesn't need an extra one like that, only at the end to reinterpret the result as unsigned.