I wrote a simple program in c which calls a function called while_loop with arguments 4,3,2. The function is just basically a while loop, I don't think it's really that relevant to my question since it's more of a generic question. I was told to run objdump -d, so I did.
I have multiple questions so here it goes:
- I understand that in the leftmost column there are addresses and they increment according to the number of bytes in front. What I don't understand very well is the second column. Is it the instruction being executed but in hexadecimal? Does that mean push %ebp is equivalent to 55 ? I don't understand that well.
- Since this is IA-32 and it's little endian, I know that the least significant byte is stored at the lowest address. However, I don't understand if the order in which these bytes are presented is according to their place in memory. Look at line 3, "8b 55 10" does this mean lowest address has 8b in it and I will read it the other way around or does this mean 10 is at the lowest address and I'll read it the other way around?
- Are these addresses on the left absolute memory addresses or relative?
In this case your addresses are absolute because you have a position-dependent executable (not a PIE). There's a field in the ELF metadata (set by the linker) that specifies what virtual address to map the executable. You can use readelf -a
to see that and much more.
In a PIE executable the hex addresses would be relative to the "image base", which normally means relative to the start of the file. (Similar to a .o
, where the addresses count from 0
at the start of the .text
section). You can use --adjust-vma=offset
to set a base address for printing those addresses.
Yes, column 2 is a hexdump of the machine code, as single bytes in memory order. Objdump isn't interpreting them as little-endian-words or anything like that, just a pair of hex digits per byte, in order of increasing address.
x86 machine code is basically a byte-stream. Instructions are composed of
[prefixes] opcode [modrm [SIB] displacement0/8/32] [immediate8/32]
The opcode is either a single byte, or a sequence of bytes specified in memory order in Intel / AMD's documentation, e.g. 0F AF /r
for imul reg, reg/mem
Some instructions have 16-bit immediates, but normally it's 1 or 4 bytes if present at all.
Endianness is only relevant for multi-byte displacements in addressing modes, or multi-byte immediates.
e.g. mov $0x12345678, %eax
in foo.s
, assembles with gcc -c foo.s
to a .o
that disassembles as:
0: b8 78 56 34 12 mov $0x12345678,%eax
See also more links to x86 docs / manuals in SO's x86 tag wiki, including Intel's PDF manuals