任意のオペコードの意味を調べる比較的速くて簡単メソッドとは何ですか(たとえば、0xC8
)x86で?
インテルソフトウェア開発者向けマニュアルを検索するのはあまり面白くない...
チェック このx86asm.netのx86オペコードの完全なテーブル を確認してください。
CTRL+F
だけで完了です。たとえば、C8
が複数の場所に表示される場合があるため、必ず正しい行を読んでください。
これはかなりいいビジュアルです。詳細については説明しませんが、16進値をすばやく検索する必要がある場合は、これで十分です。
ソース: http://pnx.tf/files/x86_opcode_structure_and_instruction_overview.png
Intel Software Developer's Manual自体を検索するのは明らかに非常に便利ではありませんが、このマニュアルのオペコード表が役立つ場合があります。マニュアルのボリューム2Bにある付録A「オペコードマップ」をご覧ください。役立つ場合があります。
オペコードを検索するための高速リファレンスは sandpile です。 0xc8の動作を確認するには、2回クリックする必要があります(enter
、btw)。
asmjit/asmdb プロジェクトもあります。これは、JSONのような形式でパブリックドメイン X86/X64データベース を提供します(実際にはノードモジュールであり、ノードから必要なだけです)またはブラウザに含めます)。追加の処理(バリデーター、アセンブラー、逆アセンブラーなど)向けに設計されていますが、データベースファイルを開いて調べることも非常に簡単です。
AsmDBには、x86util.jsと呼ばれるツールが付属しています。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 Explorer。
別の方法として、デバッガー(gdb、windbg、ollydbgなど)または逆アセンブラー(IDA)を使用して、書き込み可能なメモリ領域にバイトシーケンスを設定します。最後に、そのバイトシーケンスの開始アドレスで逆アセンブリします。
シームは複雑ですが、クラック/リバースする場合に役立ちます。
Sandpile はおそらくあなたが探しているものです。それでも、x86エンコーディングを確認する最良の方法は、16進数ではなく、octalである。突然、x86は見苦しくなりません。これについての古典的な説明は、1992年頃のUsenet alt.lang.asmによるものです。