7

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?

asked Aug 12, 2014 at 9:54
5
  • 2
    Endianness doesn't affect a bit order inside single byte. BitArray works according to its definition: The Least Significant Bit of each byte represents the lowest index value: " bytes [0] & 1" represents bit 0, " bytes [0] & 2" represents bit 1, " bytes [0] & 4" represents bit 2, and so on. msdn.microsoft.com/en-us/library/x1xda43a%28v=vs.110%29.aspx Commented Aug 12, 2014 at 10:05
  • So, it looks like your attempt to handle endianness, trying to read single byte from Modbus is kind of overkill. Just use these bytes as is, unless the protocol sends words or double words. Commented Aug 12, 2014 at 10:07
  • Your first comment: Ah. I should have looked more closely. So it is: ba[0] is always the LSB? Your second comment: Well, if I get just one byte of data returned (which is a valid use case) and have to access the bits of that one byte I wouldn't count that as overkill Commented Aug 12, 2014 at 10:47
  • I mean: endianness is not related, when you read a single byte.Only when you read words, double words and greater numbers, you need to think about endianness. Again, bits order inside a single byte is not affected (unless communication protocol uses reversed bits order, which should be mentioned in the documentation). To access the bits you can use BitArray or bitwise operations - this is your choice. Commented Aug 12, 2014 at 11:14
  • OK, so I had the whole "Endian"-part just for completeness in the question, because there are 4 combinations of the two. You are right, endianess is not part of the one-byte problem Commented Aug 12, 2014 at 11:17

2 Answers 2

0

Instead of concerning yourself with determining the endianness of the remote system, have you tried using IPAddress.HostToNetworkOrder on the host sending data and then IPAddress.NetworkToHostOrder on the receiving side? This way, you make your code agnostic to the effects of endianneas.

http://msdn.microsoft.com/en-us/library/system.net.ipaddress.hosttonetworkorder(v=vs.110).aspx

http://msdn.microsoft.com/en-us/library/system.net.ipaddress.networktohostorder(v=vs.110).aspx

answered Aug 12, 2014 at 11:24
Sign up to request clarification or add additional context in comments.

1 Comment

Well, I don't need to determine the endianess of the remote system, I know what endianess it wants and what it returns. Also the functions you provided are interesting to remember, but as I want to read single bits in the correct order from a byte, they are no use here, for they only work with ints. (word to long)
0

Now, after just a few comments I got the answer I was looking for. Had I been looking more closely I would have stumbled over it myself.

As pointed out by @Alex Farber the MSDN states that the LSB has the lowest index in a BitArray. I found this answer also here: https://stackoverflow.com/a/9066924/1968308

answered Aug 12, 2014 at 11:25

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.