Little and Big endian Architecture

In Daily life we right One Hundred Twenty Three as "1 2 3" with the hundred digit 1 left-most. This is big endian convention.
The little-endian way of writing the same number would be to put the ones digit 3 in the left-most position: "3 2 1".


little-endian: lower bytes first
big-endian: higher bytes first 


Consider the storage of the value ABCD
Here,

A-MSB(Most Significant Byte).
B
C
D-LSB(Least Significant Byte).

In Little Endian Architecture, LSB is at the lowest address of the memory location. Suppose memory location starts with 0
D->0
C->1
B->2
A->3
Intel Processors(CPUs) are Little Endian.

In Big Endian Architecture, MSB is at the lowest address of the memory location. As shown below.
A->0
B->1
C->2
D->3
While Motorola 680x0 CPUs are big-endian




What happens when little and big endian machine communicate each other ?





Constructing Messages - Byte Ordering :


Solution: Network Byte Ordering
Host Byte-Ordering: the byte ordering used by a host (big or little)
Network Byte-Ordering: the byte ordering used by the network –always big-endian
  • u_long htonl(u_long x);
  • u_short htons(u_short x);
  • u_long ntohl(u_long x);
  • u_short ntohs(u_short x);
On big-endian machines, these routines do nothing
On little-endian machines, they reverse the byte order
 


How to see memory representation of multibyte data types on your machine?
 
A sample C code that shows the byte representation of int, float and pointer.

#include <stdio.h>
/* function to show bytes in memory, from location start to start+n*/
void mem_rep(char *start, int n)
{
    int i;
    for (i = 0; i < n; i++)
         printf(" %.2x", start[i]);
    printf("\n");
}
/*Main function to call above function for 0x12345678*/
int main()
{
   int i = 0x12345678;
   mem_rep((char *)&i, sizeof(i));
   getchar();
   return 0;
}
When above program is executed on little endian machine, gives “78 56 34 12" as output , while if it is executed on big endian machine, gives “12 34 56 78" as output.

There is a quick way to determine endianness of your machine?

#include <stdio.h>
int main()
{
   unsigned int x = 1;
   char *c = (char*)&x;
   if (*c)   
       printf("Little Endian");
   else
       printf("Big Endian");
   getchar();
   return 0;
}
Based on compiler if integer size is 4 byte then :
x in binary format
(Big Endian):     00000000 00000000 00000000 00000001 
(Little Endian) : 00000001 00000000 00000000 00000000
(char*)&x =  00000001 -->(Little Endian) 00000000--->(Big Endian)

In the above program, a character pointer c is pointing to an integer x. Since size of character is 1 byte when the character pointer is de-referenced it will contain only first byte of integer. If machine is little endian then *c will be 1 (because last byte is stored first) and if machine is big endian then *c will be 0.


The Simplest way to check that your machine is Little or Big Endian ?

1. Write a simple C program as below :
/* main.c */
#include <stdio.h>
int main()
{
  return 0;
}

2. Don't worry about the below large output of readelf linux command, Only you have to observe the Data Field highlighted below :

[root@~]#gcc -c main.c -o main.o
[root@~]#ls
main.c          main.o
[root@~]#readelf -a main.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          204 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         9
  Section header string table index: 6

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000023 00  AX  0   0  4
  [ 2] .data             PROGBITS        00000000 000058 000000 00  WA  0   0  4
  [ 3] .bss              NOBITS          00000000 000058 000000 00  WA  0   0  4
  [ 4] .note.GNU-stack   PROGBITS        00000000 000058 000000 00      0   0  1
  [ 5] .comment          PROGBITS        00000000 000058 00002e 00      0   0  1
  [ 6] .shstrtab         STRTAB          00000000 000086 000045 00      0   0  1
  [ 7] .symtab           SYMTAB          00000000 000234 000080 10      8   7  4
  [ 8] .strtab           STRTAB          00000000 0002b4 00000d 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no program headers in this file.

There are no relocations in this file.

There are no unwind sections in this file.

Symbol table '.symtab' contains 8 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    2
     4: 00000000     0 SECTION LOCAL  DEFAULT    3
     5: 00000000     0 SECTION LOCAL  DEFAULT    4
     6: 00000000     0 SECTION LOCAL  DEFAULT    5
     7: 00000000    35 FUNC    GLOBAL DEFAULT    1 main
 

 

No comments:

Post a Comment