In an x86-64 disassembly, why does the constant 0x12345 appear as the bytes 45 23 01 00 in the machine code?
x86-64 is little-endian, so a multi-byte immediate is stored least-significant-byte-first — 0x00012345 is laid down in memory as 45 23 01 00.
* Follow the constant 0x12345 as it is widened to 32 bits, split into bytes, and stored least-significant-byte-first — so it shows up reversed in the machine code. *
A disassembly is just a human-readable text view of raw machine-code bytes. The instruction cmp $0x12345, %edi encodes as the bytes 81 ff 45 23 01 00, and the constant is hiding in the tail. Work it out step by step:
- Value:
0x12345 - Widen to 32 bits (the immediate's field width):
0x00012345 - Split into bytes (natural order):
00 01 23 45 - Little-endian storage (reverse):
45 23 01 00
So when you're hunting a known constant in a byte dump on a little-endian machine, search for its bytes reversed. On a big-endian target (e.g. some ARM builds, "network byte order") the very same value would appear in natural order, 00 01 23 45.
Tip: This byte-reversal is the single most common thing that makes hand-reading x86 machine code confusing — spotting it is a core reverse-engineering reflex.
Go deeper:
Compiler Explorer (godbolt.org) — write C and watch the exact machine-code bytes and disassembly the compiler emits.
Disassembler (Wikipedia) — turning raw machine-code bytes back into readable assembly.