Consider the following code, compiled on a 32-bit Ubuntu 14.04.2
with gcc 4.8.2
#include
int main(){
_exit(0)
The meaning of the MODRM byte is the same for opcode 0xFF as it is for any other instruction that uses the MODRM byte.
Your best reference for this are the online Intel Instruction set manuals. Section 2 and the page on the JMP instructions are the ones you need to interpret the MODRM bits properly for this opcode.
The interpretation of "0x25"is:
MOD=00 and R/M = binary 101 mean "use disp32" (a 32 bit address) following the MODRM byte. The 32 bit offset following the MODRM byte is the memory location. You can see it matches the value in the disassembled jmp instruction in your debug listing.
You might be confused about what opcode 0xFF means; it does not necessarily mean "JMP". The x86 often uses the MODRM Reg/Opcode bits to modify the meaning of the opcode byte, to pick out a particular instruction.
With opcode 0xFF, the Reg/Opcode bits are interpreted as more opcode bits:
Actually, those last 4 bytes are not the target address. The instruction ff 25 0c a0 04 08
is an instance of jmp rm32
(jump absolute indirect), the last 4 bytes are actually the address from which the jump target will be read.
The ModRM byte 25h, as you can see in this table, has a /digit part of 4 (that makes it a jmp rm32
, other instructions that have opcode byte ff
are inc rm32
, dec rm32
, call rm32
, call m16:32
, jmp m16:m32
, push rm32
, all distinguished by the ModRM byte). The rest of the ModRM byte 25h means that the operand is a memory address of the form [sdword]
.