Question

If I have a int32 type integer in the 8-bit processor's memory, say, 8051, how could I identify the endianess of that integer? Is it compiler specific? I think this is important when sending multybyte data through serial lines etc.

Was it helpful?

Solution

With an 8 bit microcontroller that has no native support for wider integers, the endianness of integers stored in memory is indeed up to the compiler writer.

The SDCC compiler, which is widely used on 8051, stores integers in little-endian format (the user guide for that compiler claims that it is more efficient on that architecture, due to the presence of an instruction for incrementing a data pointer but not one for decrementing).

OTHER TIPS

If the processor has any operations that act on multi-byte values, or has an multi-byte registers, it has the possibility to have an endian-ness.

http://69.41.174.64/forum/printable.phtml?id=14233&thread=14207 suggests that the 8051 mixes different endian-ness in different places.

The endianness is specific to the CPU architecture. Since a compiler needs to target a particular CPU, the compiler would have knowledge of the endianness as well. So if you need to send data over a serial connection, network, etc you may wish to use build-in functions to put data in network byte order - especially if your code needs to support multiple architectures.

For more information, see: http://www.gnu.org/s/libc/manual/html_node/Byte-Order.html

It's not just up to the compiler - '51 has some native 16-bit registers (DPTR, PC in standard, ADC_IN, DAC_OUT and such in variants) of given endianness which the compiler has to obey - but outside of that, the compiler is free to use any endianness it prefers or one you choose in project configuration...

An integer does not have endianness in it. You can't determine just from looking at the bytes whether it's big or little endian. You just have to know: For example if your 8 bit processor is little endian and you're receiving a message that you know to be big endian (because, for example, the field bus system defines big endian), you have to convert values of more than 8 bits. You'll need to either hard-code that or to have some definition on the system on which bytes to swap.

Note that swapping bytes is the easy thing. You may also have to swap bits in bit fields, since the order of bits in bit fields is compiler-specific. Again, you basically have to know this at build time.

unsigned long int x = 1;
unsigned char *px = (unsigned char *) &x;

*px == 0 ? "big endian" : "little endian"

If x is assigned the value 1 then the value 1 will be in the least significant byte. If we then cast x to be a pointer to bytes, the pointer will point to the lowest memory location of x. If that memory location is 0 it is big endian, otherwise it is little endian.

#include <stdio.h>

union foo {
    int as_int;
    char as_bytes[sizeof(int)];
};

int main() {
    union foo data;
    int i;
    for (i = 0;  i < sizeof(int);  ++i) {
        data.as_bytes[i] = 1 + i;
    }
    printf ("%0x\n", data.as_int);
    return 0;
}

Interpreting the output is up to you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top