Post by olcott Post by Andrew Cooper
There is *always* a ModRM byte. You know this because you know the
opcode FF always has one.
FF D1 - CALL ecx
The ModRM byte is D1, encoding just ecx.
FF 55 08 - CALL DWORD [ebp + 8]
The ModRM byte is 55, encoding ebp, and also that a single byte
immediate (08) follows.
FF 15 0b020000 - CALL DWORD [0000020b]
The ModRM byte is 15, encoding a memory address composed only of a
4-byte immediate value.
If you want to start getting into SIB, then you want the more
FF 14 03 - CALL DWORD [ebx + eax]
The ModRM byte is 14 (doesn't encode any registers, but does encode a
presence of SIB), and the SIB byte is 03, encoding a base of ebx, index
of eax, and a scale of 1.
In all cases, the value of the ModRM byte controls what follows. It
might be nothing, or it might be an immediate (1, 2 or 4 bytes), and/or
there might be a SIB.
FF 54 03 08 - CALL DWORD [ebx + eax + 8]
The ModRM byte is 54, encoding both a SIB byte (03) and a 1-byte
immediate (08) to follow.
I need to know how to decode this to understand that it whether or not
to look for a ModRM byte a SIB byte both or neither for all instructions.
FF /2 CALL r/m16 Call near, absolute indirect, address given in r/m16
FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32
Is the /2 somehow supposed to tell us this?
It's part of the opcode. It overflows from the 8 bits in the first byte
into those 3 bits from the Mod/Reg/RM byte.
On page 93 it shows two separate encodings for the 0xff opcode. The
first is the /2, and the second is the /3. That means you'll find the
bit pattern 010 in the Reg bits.
If you look on page 42, it says: "/digit - A digit between 0 and 7
indicates that the Mod/Reg/RM byte of the instruction uses only the RM
(register or memory) operand. The Reg field contains the digit that
provides an extension to the instruction's opcode."
In cases where you see the "/r" encoding, that means the Reg field
actually does contain a register. This would be for two-operand
sources, like "mov eax,ebx". In that case, it would use both the Reg
and RM components to indicate the two registers. In the case of "call
ecx" you're only using one register, so the Reg bits are opened up as
not being in use, and the x86 designers decided to use those bits to
allow for additional encodings.
For the CALL instruction, they added /2 and /3, which yields two
completely different call operations, such as call r/m32, and call
m16:16, or call m16:32 depending on which mode you're in, either
natively, or due to override prefixes.
Fast-forward to page 186, and you see the DEC instruction uses the 0xff
/1 encoding, meaning the same 0xff opcode, but the /1 indicates it's not
a CALL instruction, but rather a DEC instruction.
Rick C. Hodgin