I'm trying to get my head around endianess and bit ordering.
EDIT: As pointed out in the comments, the endianess doesn't concern my problem, but I like to have it put up here just for completeness. At least no one contradicted my "definitions".
What I have learned so far: If a value (perhaps a word) is comprised of more than one byte (word: 2 bytes) there are two different ways to hold that value in a continuous block of memory. Let's say we have a value of decimal 43210 (0xA8CA, 1010100011001010)
BigEndian (first) saves the byte which would have a greater effect on the values magnitude at the lower address, a bit like we write normal arabic numbers.
Memory address | 1000 | 1001 ---------------|--------|--------- Bytes | A8 | CA
LittleEndian (first) saves the byte which would have a smaller effect on the values magnitude at the lower address
Memory address | 1000 | 1001 ---------------|--------|--------- Bytes | CA | A8
Is this correct?
The second thing I have learned is, that there are two different ways to save bits of one byte in memory (sticking with 43210 and BigEndian):
Most significant bit (first/left) saves, analoguos BigEndian for bytes, the bits having the greatest impact on the values magnitude first in memory, again: as we write our arabic numbers.
Memory address | 1000 | 1001 Bit values |128|64 |32 |16 |8 |4 |2 |1 |128|64 |32 |16 |8 |4 |2 |1 | -------------------------------------------------------------------------------- Bits | 1 0 1 0 1 0 0 0 | 1 1 0 0 1 0 1 0
Least significant bit (first/left) reverses the order of bits within a byte, so the bit differentiating between an even and uneven number comes first
Memory address | 1000 | 1001 Bit values |1 |2 |4 |8 |16 |32 |64 |128|1 |2 |4 |8 |16 |32 |64 |128| -------------------------------------------------------------------------------- Bits | 0 0 0 1 0 1 0 1 | 0 1 0 1 0 0 1 1
Is that also correct?
Here comes my scenario and Problem: I am receiving data over network. The protocol (Modbus) specifies a) data transfer as BigEndian and when bits have to be returned, wrapped up in bytes, the MSB is to the left and the LSB to the right. I am programming in C#, .Net 4.5.
On many an occasion I have made use of the BitConverter-class to check for the endianess of my system (BitConverter.IsLittleEndian
) to correctly pass word-values through my NetSocket.
public static byte[] CorrectEndianess(byte[] in_byteArray)
{
if (BitConverter.IsLittleEndian)
return in_byteArray.Reverse().ToArray();
else return in_byteArray;
}
It all grinds to a halt when I receive a byte containing eight bits representing the state of eight coils (or inputs). By definition the Modbus protocol delivers the following (example):
Coil No. (example) | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 |
-------------------|---------------------------------------|
Bits |MSB LSB|
Example values | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
The byte
containing this information is shown in the debugger to have the value "1", which is nice. I need, however, every single bit as boolean value. C# provides the BitArray
, a class I can pass bytes, which returns a bool[]
, ideal for my purposes.
BitArray ba = new BitArray(new byte[1] { my_byte_which_is_of_value_1 });
If I print the BitArrays array, ba[0]
contains the value true
, the rest false
. So I figure that BitArray thinks that a single byte is LSB first. Which is odd, because it breaks the remaining handling of the bits, which expects (for the example) ba[7]
to be true
.
Long story short, here is my main question:
How can I check which bit ordering is assumed in BitArray
or in byte
, so I always know where my LSB and MSB are?
On a sidenote: Are numbers in right-to-left-notation-languages written BigEndian right?