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 ?
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
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
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 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