vb.netbit-manipulationbit-shift16-bit8-bit

16 bit register converting to two 8 bytes using vb.net in visual studio


converting the 16 bit data to 8 bit and then reversing it back to 16 bits

Module Module1
    Sub Main()
        ' Original 16-bit data
        Dim originalValue As UShort = &HA91

        ' Split into two 8-bit values
        Dim highByte As Byte = CByte((originalValue >> 8) And &HFF)
        Dim lowByte As Byte = CByte(originalValue And &HFF)

        ' Display the split values
        Console.WriteLine("High Byte: 0x{0:X2}", highByte)
        Console.WriteLine("Low Byte:  0x{0:X2}", lowByte)

        ' Combine the two 8-bit values back into a 16-bit value
        Dim combinedValue As UShort = CUShort((CUShort(highByte) << 8) Or CUShort(lowByte))

        ' Display the combined value
        Console.WriteLine("Combined Value: 0x{0:X3}", combinedValue)

        ' Check if the original value matches the combined value
        If originalValue = combinedValue Then
            Console.WriteLine("The values match!")
        Else
            Console.WriteLine("The values do not match!")
        End If

        Console.ReadLine()
    End Sub
End Module

i am getting 2570 instead of 2705 for hex value of &HA91


Solution

  • It's unclear why one would need to recombine the low byte and high byte. Nonetheless, the following should resolve your issue. Change the following code

    From:

    ' Combine the two 8-bit values back into a 16-bit value
    Dim combinedValue As UShort = CUShort((highByte << 8) Or lowByte)
    

    To:

    ' Combine the two 8-bit values back into a 16-bit value
    Dim combinedValue As UShort = (CUShort(highByte) << 8) Or lowByte
    

    Here's the explanation. To understand the issue, let's look at a truth table.

    Truth table for conjunction (AND)

    p q p AND q
    1 1 1
    1 0 0
    0 1 0
    0 0 0

    Truth table for disjunction (OR)

    p q p OR q
    1 1 1
    1 0 1
    0 1 1
    0 0 0

    Note: I recommend using the built-in Windows calculator - using the menu to select Programmer mode. To enter a HEX value, click on HEX prior to using the keypad. Likewise, to enter a decimal value, click on DEC prior to using the keypad. As you may already know, to enter a binary value, one clicks on BIN prior to using the keypad.

    Let's look at the value &HA91:

    The highByte (ie: most significant byte) value is: 0A (binary: 0000 1010)

    The lowByte (ie: least significant byte) value is: 91 (binary: 1001 0001)

    Let's look at some code:

    Console.WriteLine($"shifted value: {(highByte << 8).ToString("X8")}")
    

    Result:

    shifted value: 0000000A
    

    According to << Operator (Visual Basic):

    • Result: Integral numeric value. The result of shifting the bit pattern. The data type is the same as that of pattern.

    • Pattern: Integral numeric expression. The bit pattern to be shifted. The data type must be an integral type (SByte, Byte, Short, UShort, Integer, UInteger, Long, or ULong).

    • Amount: Numeric expression. The number of bits to shift the bit pattern. The data type must be Integer or widen to Integer.

    To prevent shifting by more bits than the result can hold, Visual Basic masks the value of amount with a size mask corresponding to the data type of pattern. The binary AND of these values is used for the shift amount. The size masks are as follows:

    Data type of pattern Size mask (decimal) Size mask (hexadecimal)
    SByte, Byte 7 &H00000007
    Short, UShort 15 &H0000000F

    If amount is zero, the value of result is identical to the value of pattern.

    In the code in the OP, is the following:

    Dim originalValue As UShort = &HA91
    Dim highByte As Byte = CByte((originalValue >> 8) And &HFF)
               ...
    Dim combinedValue As UShort = CUShort((highByte << 8) Or lowByte)
    

    Let's look at the following: highByte << 8.

    highByte is a Byte and a left shift by 8 is being done. According to the documentation, a check is performed.

    Description
    8 1000
    7 0111
    8 AND 7 0000

    As previously stated above: If amount is zero, the value of result is identical to the value of pattern (ie: highByte).

    What happens if we do highByte OR lowByte?

    Description
    highByte 0000 1010
    lowByte 1001 0001
    highByte OR lowByte 1001 1011

    highByte OR lowByte = 1001 1011 = Hexadecimal 9B.

    What happened? One needs to have a UInt16 (or UShort) before shifting the bits left.


    According to >> Operator (Visual Basic):

    Note that the data types Byte, UShort, UInteger, and ULong are unsigned, so there is no sign bit to propagate. If pattern is of any unsigned type, the vacated positions are always set to zero.

    which means:

    Dim highByte As Byte = CByte((originalValue >> 8) And &HFF)
    

    can be changed to

    Dim highByte As Byte = CByte(originalValue >> 8)