I\'ve got the 32bit opcode: FF 35 0E 20 40 00
. Does anybody know a good OpCode table that gives an answer to this? (I know I could use a disassembler, but I\'d
Let's try going through this byte sequence one byte at a time.
FF
. Looking it up in the Opcode Map in the Intel Instruction Set Reference tells us that this is an INC
or a DEC
instruction, along with the cryptical "Grp 5 - 1A". The 1A means that "Bits 5, 4, and 3 of ModR/M byte used as an opcode extension". The ModR/M byte is the byte that encodes the source and the address of the operands that are used for this instruction. In this case, the three bits are used for extending the opcode.35
. This is the ModR/M byte, which normally appears right after the opcode itself, in instructions that use it. 35
(in hex) is 00110101
in binary, so bits 5, 4, and 3 are 110
. Looking this up in the opcode extension table (Table A-6) we can see that this means this is a PUSH d64 Ev
instruction. The d64
footnote means that "When in 64-bit mode, instruction defaults to 64-bit operand size and cannot encode 32-bit operand size.". This is expected for the PUSH
instruction. Ev
is a symbol that specifies the operand encoding - most importantly, it states that a ModR/M byte follows the opcode itself. The v
, on the other hand, signals that the operand's size is dependent on the operand-size attribute. We already have the ModR/M byte, so let's decode it (Table 2-2, assuming that this code is running in 32-bit mode) : the effective address is specified by a disp32
, which means that a 32-bit displacement should follow the ModR/M byte. The part specifying the register says that ESI
should be used, but in this case this field is used for the opcode extension, so it isn't used to signify a register source operand.0E 20 40 00
, when decoded as little endian, means 0x40200e
. This is the address of the operand that will be used for this instruction.Summing it all up, we got that FF 35 0E 20 40 00
is PUSH DWORD [0x40200e]
, i.e. it will push the 32-bit value read from the address 0x40200e
on the stack.
You're looking in the wrong place. You should looking this in Intel's or AMD's official documentation.
Appendix A Opcode Map
of Vol 2B
of Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 3A and 3B
says that FF
is INC/DEC Grp5
1A
.
Table A-6 Opcode Extensions for One- and Two-byte Opcodes by Group Number
of Vol 2B
says FF
/Group 5
either of INC
, DEC
, CALLN
, CALLF
, JMPN
, JMPF
, PUSH
, depending on bits 5 through 3 of the ModR/M
byte, the byte that follows. (0x35>>3)&7=6 or 110 in binary. So, this is PUSH Ev
.
Chapter 2 Instruction Format
of Vol 2A
explains what parts an instruction consists of, including those ModR/M
bytes and what not.
Appendix A Using Opcode Tables
of Vol 2B
tells you for E
:
A ModR/M byte follows the opcode and specifies the operand. The operand is either a general-purpose register or a memory address. If it is a memory address, the address is computed from a segment register and any of the following values: a base register, an index register, a scaling factor, a displacement.
It also tells you for v
:
Word, doubleword or quadword (in 64-bit mode), depending on operand-size attribute.
So, you know that Ev
means a register or a memory operand and since this is for 32-bit code and there are no instruction prefixes, the operand size is 32 bits. So, Ev
a 32-bit register or a 32-bit variable in memory.
Now you need to figure out the rest of the bytes from ModR/M until the end.
Look at Figure 2-1. Intel 64 and IA-32 Architectures Instruction Format
of Vol 2A
. It tells you that in ModR/M
=0x35:
Mod
= 00 (binary)
Reg
= 110 (binary; we've extracted these 3 bits before)
R/M
= 101 (binary)
Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte
of Vol 2A
tells you that Mod
= 00 and R/M
= 101 means disp32
, IOW, there's a memory operand consisting of a 32-bit displacement in the instruction.
The Reg
field of the ModR/M
byte has already been used to choose one of the seven instructions and therefore this field does not encode a register operand.
So, your instruction is PUSH DWORD [0x0040200E]
.
And that agrees with my disassembler output.