From: rick.c.hodgin@nospicedham.gmail.com   
      
   On 11/25/20 5:14 PM, olcott wrote:   
   >> As for `CALL indirect`, the general form looks like this:   
   >>   
   >> FF    
   >>   
   >> There is *always* a ModRM byte. You know this because you know the   
   >> opcode FF always has one.   
   >>   
   >> From the examples given previously:   
   >>   
   >> 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   
   >> complicated addressing modes, such as:   
   >>   
   >> 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.   
   >>   
   >> An example using both might be:   
   >>   
   >> 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.   
   >>   
   >> ~Andrew   
   >>   
   >   
   > 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.   
      
   Make sense?   
      
   --   
   Rick C. Hodgin   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|