Intel x86 Opcode Reference?
Asked Answered
G

7

44

What is a relatively quick and easy method of looking up what an arbitrary opcode means (say, 0xC8) in x86?

The Intel Software Developer's manual isn't very fun to search through...

Goeselt answered 19/6, 2011 at 9:19 Comment(1)
The Intel manual does have a table of opcodes in an appendix, but I agree it's not as nice to use as other resources for manually disassembling.Kinetics
R
60

Check this very complete table of x86 opcodes on x86asm.net.

Just CTRL+F and you're done! Be sure to read the correct line tho, as C8 for example may appear in several locations.

Reed answered 19/6, 2011 at 9:32 Comment(1)
FYI, that page is no longer "very complete". It seems to stop before AVX. (Try finding vmovups for example.) It's otherwise a great reference though, so this is a good answer. But if people want something "very complete", the only reference I see now is Sandpile, as others mention. Though there is also AsmJit's database, which might also be helpful. Finally, for the benefit of anyone who doesn't scroll down to read other answers: x86 is much more readable in octal, grouping the bits as [AA][BBB][CCC].Goeselt
C
30

Here is a pretty nice visual. Doesn't go into much detail, but if you just need to look up a hex value really quick, this should do it-

Opcode reference

Source: http://pnx.tf/files/x86_opcode_structure_and_instruction_overview.pdf

Callida answered 9/9, 2015 at 19:25 Comment(5)
most exciting table I have ever seenSeamaid
Why is XCHG EAX, ECX Memory?Nidanidaros
@Nidanidaros possibly because EAX is a registerCallida
@l4m2: It's not, that's mis-categorized. It's not doing any computation, just data movement, but the data movement for the 0x90..7 xchg eax, reg single-byte encodings can't include data memory. Neither do the 0xb? mov opcodes that put an imm8 or imm32 into a register. Also, cwd and cdq are clearly ALU instructions, sign-extending EAX into EDX:EAX. Wait a minute, that table isn't even right. 0x98 is CWDE (and with a 66 prefix, CBW). 0x99 is CDQ (and with a 66 prefix, CWD).Kinetics
@l4m2: so I guess we can take the red colour as actually being "data movement", including shuffles like bswap. But 0x98 is mislabeled as CWD when it's actually CWDE, and that's clearly ALU, setting one register according to the top bit of another register. Also, CMPS and SCAS aren't exactly "control flow", they're both memory and ALU. repe scasb is a branchless (and slow) memchr, for example. If you had to pick one colour for those, IDK. I guess their "control flow and conditional" includes flag-setting / reading for some reason, even though that's just ALU.Kinetics
R
14

While Intel Software Developer's Manual itself is definitely not very convenient to search through, the opcode tables in this manual could help. Take a look at the Appendix A "Opcode Map" in the volume 2A, 2B, 2C, and 2D of the manual, it might be useful:

Appendix A Opcode Map Table of Contents

Riel answered 19/6, 2011 at 9:52 Comment(2)
It's probably just me, but I'm finding the appendix slightly confusing. :\ Thanks though.Goeselt
I added a direct link to the PDF manual and a screenshot of the Table of Contents for Appendix A. I found it from this entry page > software.intel.com/content/www/us/en/develop/articles/… which linked to the 4 part combined manual here > software.intel.com/content/www/us/en/develop/download/…, in case the link ever needs updating.Greige
O
9

There is also asmjit/asmdb project, which provides public domain X86/X64 database in a JSON-like format (it's a node module actually, just require() it from node or include in browser). It's designed for additional processing (for example to write validators, assemblers, disassemblers), but it's also very easy to just open the database file and explore it.

AsmDB comes with a tool called x86util.js, which can index the x86 database into much more friendly representation that can be used to actually do something with it. Let's write a simple tool in node.js that prints all instructions that have the same opcode byte as you provide:

const asmdb = require("asmdb");
const x86isa = new asmdb.x86.ISA();

function printByOpCode(opcode) {
  x86isa.instructions.forEach(function(inst) {
    if (inst.opcodeHex === opcode) {
      const ops = inst.operands.map(function(op) { return op.data; });
      console.log(`INSTRUCTION '${inst.name} ${ops.join(", ")}' -> '${inst.opcodeString}'`);
    }
  });
}

if (process.argv.length < 3)
  console.log("USAGE: node x86search.js XX (opcode)")
else
  printByOpCode(process.argv[2]);

Try it:

$ node x86search.js A9
INSTRUCTION 'pop gs' -> '0F A9'
INSTRUCTION 'test ax, iw' -> '66 A9 iw'
INSTRUCTION 'test eax, id' -> 'A9 id'
INSTRUCTION 'test rax, id' -> 'REX.W A9 id'
INSTRUCTION 'vfmadd213sd xmm, xmm, xmm/m64' -> 'VEX.DDS.LIG.66.0F38.W1 A9 /r'
INSTRUCTION 'vfmadd213sd xmm, xmm, xmm/m64' -> 'EVEX.DDS.LIG.66.0F38.W1 A9 /r'
INSTRUCTION 'vfmadd213ss xmm, xmm, xmm/m32' -> 'VEX.DDS.LIG.66.0F38.W0 A9 /r'
INSTRUCTION 'vfmadd213ss xmm, xmm, xmm/m32' -> 'EVEX.DDS.LIG.66.0F38.W0 A9 /r'

$ node x86search.js FF
INSTRUCTION 'call r32/m32' -> 'FF /2'
INSTRUCTION 'call r64/m64' -> 'FF /2'
INSTRUCTION 'dec r16/m16' -> '66 FF /1'
INSTRUCTION 'dec r32/m32' -> 'FF /1'
INSTRUCTION 'dec r64/m64' -> 'REX.W FF /1'
INSTRUCTION 'fcos ' -> 'D9 FF'
INSTRUCTION 'inc r16/m16' -> '66 FF /0'
INSTRUCTION 'inc r32/m32' -> 'FF /0'
INSTRUCTION 'inc r64/m64' -> 'REX.W FF /0'
INSTRUCTION 'jmp r32/m32' -> 'FF /4'
INSTRUCTION 'jmp r64/m64' -> 'FF /4'
INSTRUCTION 'push r16/m16' -> '66 FF /6'
INSTRUCTION 'push r32/m32' -> 'FF /6'
INSTRUCTION 'push r64/m64' -> 'FF /6'

Additionally, there are command line tools that can be used for quick and dirty disassembling, but these require the whole instruction (in contrast of having just the opcode byte), here are some tips:

Using llvm-mc from LLVM project:

$ echo "0x0f 0x28 0x44 0xd8 0x10" | llvm-mc -disassemble -triple=x86_64 -output-asm-variant=1
.text
movaps xmm0, xmmword ptr [rax + 8*rbx + 16]

Using ndisasm from nasm project:

$ echo -n -e '\x0f\x28\x44\xd8\x10' | ndisasm -b64 -
00000000 0F2844D810 movaps xmm0,oword [rax+rbx*8+0x10]

There is also an AsmGrid project from the same author as AsmDB. It a work-in-progress online AsmDB explorer that uses colors to visualize various properties of each instruction.

Octavalent answered 5/9, 2016 at 17:41 Comment(0)
A
8

A fast reference for looking up opcodes is sandpile. I need two clicks to find out what 0xc8 does (it's enter, btw).

Afrikaner answered 20/6, 2011 at 9:30 Comment(0)
B
6

Sandpile is probably what you're looking for. Still, the best way to look at the x86 encoding is not in hex but rather in octal. Suddenly x86 doesn't look so ugly and it makes some sense.

The classic explanation of this was available at Usenet alt.lang.asm circa 1992, however, today is available in github

Barhorst answered 13/8, 2016 at 21:43 Comment(1)
Hmm, interesting. x86 has 8 registers, and a few opcodes use the low 3 bits to encode a destination register (including inc r32, dec r32, xchg r32, eax, and mov r32, imm32). This makes it natural to have groups of 3 bits in the encoding for other instructions, too.Kinetics
C
3

Another way, using a debugger (gdb, windbg, ollydbg, ...) or disassembler (IDA), and then, set byte sequences in writable memory region. Finally, disassembly at the starting address of that byte sequences.
It's seam complicated, but useful in some situations when you cracking/reversing.

Commission answered 7/6, 2012 at 20:13 Comment(1)
hiew -- yet another powerful console disassembler (with an ability to assembly inline commands) perfectly fits all basic cracking needs. I recommend run it from within FAR manager as binary editor.Seamaid

© 2022 - 2024 — McMap. All rights reserved.