【问题标题】:Intel x86 Opcode Reference?英特尔 x86 操作码参考?
【发布时间】:2011-09-18 02:21:36
【问题描述】:

什么是在 x86 中查找任意操作码(例如,0xC8)含义的相对快速和简单的方法?

Intel Software Developer's manual 搜索起来不是很有趣...

【问题讨论】:

  • 英特尔手册确实在附录中有一个操作码表,但我同意它不像其他资源那样用于手动反汇编。

标签: assembly x86 intel opcode


【解决方案1】:

检查this very complete table of x86 opcodes on x86asm.net

只需CTRL+F,您就完成了!请务必阅读正确的行,例如 C8 可能出现在多个位置。

【讨论】:

    【解决方案2】:

    虽然英特尔软件开发人员手册本身绝对不是很方便搜索,但本手册中的操作码表可能会有所帮助。看看手册volume 2A, 2B, 2C, and 2D中的附录A“Opcode Map”,可能有用:

    【讨论】:

    【解决方案3】:

    查找操作码的快速参考是sandpile。我需要点击两次才能了解 0xc8 的作用(它是 enter,顺便说一句)。

    【讨论】:

      【解决方案4】:

      另一种方式,使用调试器(gdb、windbg、ollydbg、...)或反汇编器(IDA),然后在可写内存区域中设置字节序列。最后,在该字节序列的起始地址进行反汇编。
      它的接缝很复杂,但在某些情况下当你开裂/反转时很有用。

      【讨论】:

      • hiew -- 又一个强大的控制台反汇编程序(具有汇编内联命令的能力)完美地满足了所有基本的破解需求。我建议在 FAR 管理器中作为二进制编辑器运行它。
      【解决方案5】:

      这是一个非常漂亮的视觉效果。没有详细说明,但如果您只需要快速查找十六进制值,应该这样做-

      来源:http://pnx.tf/files/x86_opcode_structure_and_instruction_overview.png

      【讨论】:

      • 我见过的最激动人心的桌子
      • 为什么是XCHG EAX, ECX内存?
      • @l4m2 可能是因为 EAX 是一个寄存器
      • @l4m2:不是,这是错误分类。它不做任何计算,只是数据移动,但0x90..7 xchg eax, reg 单字节编码的数据移动不能包括数据内存。将 imm8 或 imm32 放入寄存器的 0xb? mov 操作码也没有。此外,cwdcdq 显然是 ALU 指令,将 EAX 符号扩展为 EDX:EAX。等一下,那张桌子也不对。 0x98 is CWDE(并带有 66 前缀,CBW)。 0x99 is CDQ(并带有 66 前缀,CWD)。
      • @l4m2:所以我想我们可以将红色视为实际上是“数据移动”,包括像 bswap 这样的洗牌。但是0x98实际上是CWDE时被错误标记为CWD,这显然是ALU,根据另一个寄存器的最高位设置一个寄存器。此外,CMPS 和 SCAS 并不完全是“控制流”,它们既是内存又是 ALU。例如,repe scasb 是一个无分支(且速度较慢)的 memchr。如果您必须为它们选择一种颜色,IDK。我猜他们的“控制流和条件”出于某种原因包括标志设置/读取,即使那只是 ALU。
      【解决方案6】:

      Sandpile 可能是您正在寻找的。不过,查看 x86 编码的最佳方式不是十六进制,而是 八进制。突然间,x86 看起来不那么难看了,而且有些道理。

      1992 年左右在 Usenet alt.lang.asm 上可以找到对此的经典解释,但今天可以在 github 上找到

      【讨论】:

      • 嗯,很有趣。 x86 有 8 个寄存器,少数操作码使用低 3 位对目标寄存器进行编码(包括inc r32dec r32xchg r32, eaxmov r32, imm32)。这使得其他指令的编码中也有 3 位组很自然。
      【解决方案7】:

      还有asmjit/asmdb项目,它以类似JSON的格式提供公共域X86/X64 database(它实际上是一个节点模块,只需从节点 require() 或包含在浏览器中)。它是为额外处理而设计的(例如编写验证器、汇编器、反汇编器),但也很容易打开数据库文件并进行探索。

      AsmDB 带有一个名为 x86util.js 的工具,它可以将 x86 数据库索引为更友好的表示形式,可以用来实际使用它做一些事情。让我们在 node.js 中编写一个简单的工具,打印所有与您提供的操作码字节相同的指令:

      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]);
      

      试试看:

      $ 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'
      

      此外,还有一些命令行工具可用于快速和脏反汇编,但这些工具需要整个指令(与只有操作码字节相比),这里有一些提示:

      使用来自LLVM 项目的 llvm-mc:

      $ 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]
      

      使用来自nasm 项目的 ndisasm:

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

      还有一个与 AsmDB 同一作者的 AsmGrid 项目。它是一个正在开发中的在线 AsmDB 浏览器,它使用颜色来可视化每条指令的各种属性。

      【讨论】:

        猜你喜欢
        • 2011-04-29
        • 1970-01-01
        • 2012-09-26
        • 2011-01-29
        • 2014-04-02
        • 1970-01-01
        • 2013-02-07
        • 2012-02-25
        • 1970-01-01
        相关资源
        最近更新 更多