Everything Filip knows: Endianness
Table of Contents
Endianness or Byte-Order is a word to describe in which order bytes in a data word (the unit of data that the ALU can process at one time). Different architectures have different Endianness and as such Endianness is a well-known concern in networking or emulation. Some exotic ISAs support switching the Endianness.
1. ISAs/CPUs and their Endianness
1.1. A list of little Endian machines
- PDP-11
- VAXes
- Z80
- 6502
- x86
- AVR
- LoongArch
1.2. A list of big Endian machines
- PDP-10
- 6800
- m88k
- System/360, System/370, System/390
1.3. A list of bi-Endian machines
- Alpha
- ARM
- ARM64
- Itanium
- MIPS
- OpenRISC
- PowerPC
2. How it works
In a little Endian computer, the least significant byte is in placed in the smallest place, whereas in a big Endian computer the least significant byte at the largest. Consider the decimal number 4286742954; in little Endian systems this would be 0xFFE1234A, meanwhile on big Endian machines this would be 0xFFE1234A.
3. How to reverse it
The simplest way to reverse the byte order of a word is to not do it yourself and rely on some library function for that, for instance C++23 introduced `std::byteswap`, however it's still good to know how to do it yourself, in case you're presented with a situation, where such luxury is not available or not viable.
If you are on amd64 and don't need your code to be portable, then there is an instruction called `bswap`, which can be used to reverse Endianness.
mov eax, x bswap eax mov x, eax
Note that this assembly code only works on 32-bit words. Also note that using this as inline assembly in a C or C++ program is retarded, as the compiler will optimize almost any kind of byte-order swapping operation to use bswap (or a comparable instruction, depending on the target CPU and the word size). Most C standard libraries have a header called "byteswap.h" (even though this header is a GNU extension), it differs from libc to libc, but it should look something along these lines:
#include <stdint.h> inline uint16_t bswap_16(uint16_t x) { return (x << 8) | (x >> 8); } inline uint32_t bswap_32(uint32_t x) { return (x >> 24) | (x >> 8 & 0xff00) | (x << 8 & 0xff0000) | (x << 24); } inline uint64_t bswap_64(uint64_t x) { return (bswap_32(x) + 0ULL << 32) | bswap_32(x >> 32); }
4. Trivia
The term originates from the novel Gulliver's Travels, where the Lilliputians tried to break a boiled egg's shell, some trying to break it on the big end and the others trying to break it at the small end.
(I haven't read the book, so this description might be or be not accurate, but it seems to be the origin of this term, thus I wanted to have it in here too.)