Calculating bitwise inversion of char

537 views Asked by At

I am trying to reverse engineering a serial port device that uses hdlc for its packet format.Based on the documentation, the packet should contain a bitwise inversion of the command(first 4 bytes), which in this case is "HELO". Monitoring the serial port when using the original program shows what the bitwise inversion should be:

 HELO -> b7 ba b3 b0
 READ -> ad ba be bb

The problem is, I am not getting values even remotely close.

public object checksum
    {

        get
        {
            var cmdDec = (int)Char.GetNumericValue((char)this.cmd);
            return (cmdDec ^ 0xffffffff);
        }
    }
3

There are 3 answers

0
Dmitry Bychenko On BEST ANSWER

You have to work with bytes, not with chars:

string source = "HELO";

// Encoding.ASCII: I assume that the command line has ASCII encoded commands only  
byte[] result = Encoding.ASCII
  .GetBytes(source)
  .Select(b => unchecked((byte)~b)) // unchecked: ~b returns int; can exceed byte.MaxValue
  .ToArray();

Test (let's represent the result as hexadecimals)

// b7 ba b3 b0
Console.Write(string.Join(" ", result.Select(b => b.ToString("x2")))); 
0
Jeroen van Langen On

Char is not a byte. You should use bytes instead of chars.


So this.cmd is an array of bytes? You could use the BitConverter.ToUInt32()

PSEUDO: (you might fix some casting)

public uint checksum
{
    get
    {
        var cmdDec = BitConverter.ToUInt32(this.cmd, 0);
        return (cmdDec ^ 0xffffffff);
    }
}

if this.cmd is a string you could get a byte array from it with Encoding.UTF8.GetBytes(string)

0
Abion47 On

Your bitwise inversion isn't doing what you think it's doing. Take the following, for example:

int i = 5;

var j = i ^ 0xFFFFFFFF;
var k = ~i;

The first example is performing the inversion the way you are doing it, by XOR-ing the number with a max value. The second value uses the C# Bitwise-NOT ~ operator.

After running this code, j will be a long value equal to 4294967290, while k will be an int value equal to -6. Their binary representation will be the same, but j will include another 32 bits of 0's to go along with it. There's also the obvious problem of them being completely different numbers, so any math performed on the values will be completely different depending on what you are using.