5

I'm reading through a library (github.com/adduc/phpmodbus) and there's this function for converting integer to little-endian or big-endian string of bytes:

private static function endianness($value, $endianness = 0) {
    if ($endianness == 0)
        return
                self::iecBYTE(($value >> 8) & 0x000000FF) .
                self::iecBYTE(($value & 0x000000FF)) .
                self::iecBYTE(($value >> 24) & 0x000000FF) .
                self::iecBYTE(($value >> 16) & 0x000000FF);
    else
        return
                self::iecBYTE(($value >> 24) & 0x000000FF) .
                self::iecBYTE(($value >> 16) & 0x000000FF) .
                self::iecBYTE(($value >> 8) & 0x000000FF) .
                self::iecBYTE(($value & 0x000000FF));
}

The iecBYTE function is just chr($value & 0xFF).

Now maybe I'm thick, but the little-endian string looks wrong.
For example, with 0xAABBCCDD, you'd get {CC}{DD}{AA}{BB}.

I even looked it up on Wikipedia. Shouldn't it be {DD}{CC}{BB}{AA}?

The code works though, which really confuses me. Is it right and I understand it incorrectly?

MightyPork
  • 18,270
  • 10
  • 79
  • 133
  • 1
    What do you mean by it works? Could it perhaps be "working" but just not correctly working? – imtheman Dec 19 '14 at 17:42
  • Maybe I misunderstood what the method is doing, not sure. The method is used quite a lot in the library, and it works correctly. – MightyPork Dec 19 '14 at 17:44

2 Answers2

0

You are correct. The function is not right, though it is close. It looks like you just need to swap a few of the conversions. Logically the little-endian conversion ($endianness == 0) is just the inverse of the big-endian conversion ($endianness != 0).

private static function endianness($value, $endianness = 0) {
    if ($endianness == 0) //little-endian
        return
                self::iecBYTE($value & 0x000000FF) .
                self::iecBYTE(($value >> 8) & 0x000000FF) .
                self::iecBYTE(($value >> 16) & 0x000000FF) .
                self::iecBYTE(($value >> 24) & 0x000000FF);
    else //big-endian
        return
                self::iecBYTE(($value >> 24) & 0x000000FF) .
                self::iecBYTE(($value >> 16) & 0x000000FF) .
                self::iecBYTE(($value >> 8) & 0x000000FF) .
                self::iecBYTE(($value & 0x000000FF));
}
imtheman
  • 4,713
  • 1
  • 30
  • 30
0

After looking at the IECType.php, I noticed that it is converting PHP types to the IEC 1131 types. Little endian is storing least significant bytes first. What your describing would make me think the system is using 16-bit addresses.

If you look at the wiki for Endianess referenced in the comments above the endianess function, then you will see a section under Little-endian called Atomic element size 16-bit. One Address holds two bytes (CCDD) and (AABB). The address holding the (CCDD) is least significant so it would be listed first.

If you were working in an 8-bit system then each byte would be ordered (DDCCBBAA) because there would be one byte per address.

Wiki describes the what you are seeing in the endianess function.

address1| address2
16-bits | 16-bits
 CCDD   |  AABB
Daniel Gale
  • 643
  • 4
  • 13