70

教育プロジェクトとしてx86ディスセンブラーを作成することに興味があります。

私が見つけた唯一の実際のリソースは、SpiralSpaceの「逆​​アセンブラの書き方」です。これにより、逆アセンブラのさまざまなコンポーネントの概要がわかりやすくなりますが、より詳細なリソースに興味があります。NASMのソースコードもざっと見てきましたが、これは学ぶのにやや重いものです。

このプロジェクトの主要な課題の1つは、処理しなければならないかなり大きなx86命令セットであることを認識しています。基本的な構造、基本的な逆アセンブラリンクなどにも興味があります。

x86逆アセンブラの作成に関する詳細なリソースを教えてもらえますか?

4

5 に答える 5

67

80386プログラマーズリファレンスマニュアルのセクション17.2をご覧ください。逆アセンブラは、実際には単なる栄光の有限状態マシンです。分解の手順は次のとおりです。

  1. 現在のバイトが命令プレフィックスバイト(、、、または)であるかどうかを確認F3F2ますF0。もしそうなら、あなたは///REPプレフィックスを持っていREPEます。次のバイトに進みます。REPNELOCK
  2. 現在のバイトがアドレスサイズバイト()であるかどうかを確認します67。その場合、現在32ビットモードの場合は16ビットモードで残りの命令のアドレスをデコードし、現在16ビットモードの場合は32ビットモードでアドレスをデコードします。
  3. 現在のバイトがオペランドサイズのバイト()であるかどうかを確認します66。その場合、現在32ビットモードの場合は16ビットモードでイミディエートオペランドをデコードし、現在16ビットモードの場合は32ビットモードでイミディエートオペランドをデコードします。
  4. 現在のバイトがセグメントオーバーライドバイト( 、、、、、、、または)2E36あるかどうか3Eを確認します。その場合、デフォルトのセグメントレジスタの代わりに、アドレスのデコードに対応するセグメントレジスタを使用します。266465
  5. 次のバイトはオペコードです。オペコードが0F、の場合、それは拡張オペコードであり、次のバイトを拡張オペコードとして読み取ります。
  6. 特定のオペコードに応じて、Mod R / Mバイト、Scale Index Base(SIB)バイト、変位(0、1、2、または4バイト)、および/または即値(0、1 、2、または4バイト)。これらのフィールドのサイズは、以前にデコードされたオペコード、アドレスサイズのオーバーライド、およびオペランドサイズのオーバーライドによって異なります。

オペコードは、実行されている操作を通知します。オペコードの引数は、Mod R / M、SIB、変位、および即値の値からデコードできます。x86の複雑な性質により、多くの可能性と多くの特殊なケースがあります。より詳細な説明については、上記のリンクを参照してください。

于 2009-05-29T04:57:22.053 に答える
22

いくつかのオープンソース逆アセンブラ、できればdistorm、特に「disOps(命令セットデータベース)」(ctrl +ページで検索)を確認することをお勧めします。

ドキュメント自体は、オペコードと手順に関するジューシーな情報でいっぱいです。

https://code.google.com/p/distorm/wiki/x86_x64_Machine_Codeからの引用

80x86命令:

80x86命令は、いくつかの要素に分割されます。

  1. 命令プレフィックスは、命令の操作の動作に影響を与えます。
  2. SSE命令のオペコードバイトとして使用される必須のプレフィックス。
  3. オペコードバイトは、1つ以上のバイト(最大3バイト)にすることができます。
  4. ModR / Mバイトはオプションであり、オペコード自体の一部が含まれる場合もあります。
  5. SIBバイトはオプションであり、複雑なメモリ間接形式を表します。
  6. 変位はオプションであり、さまざまなサイズのバイト(バイト、ワード、ロング)の値であり、オフセットとして使用されます。
  7. イミディエイトはオプションであり、さまざまなサイズのバイト(バイト、ワード、ロング)から構築された一般的な数値として使用されます。

形式は次のようになります。

/-------------------------------------------------------------------------------------------------------------------------------------------\
|*Prefixes | *Mandatory Prefix | *REX Prefix | Opcode Bytes | *ModR/M | *SIB | *Displacement (1,2 or 4 bytes) | *Immediate (1,2 or 4 bytes) |
\-------------------------------------------------------------------------------------------------------------------------------------------/
* means the element is optional.

データ構造とデコードフェーズについては、https://code.google.com/p/distorm/wiki/diStorm_Internalsで説明されています。

引用:

デコードフェーズ

  1. [プレフィックス]
  2. [オペコードを取得]
  3. [フィルターオペコード]
  4. [オペランドの抽出]
  5. [テキストの書式設定]
  6. [16進ダンプ]
  7. [デコードされた命令]

各ステップについても説明します。


元のリンクは、歴史的な理由で保持されています。

http://code.google.com/p/distorm/wiki/x86_x64_Machine_Codeおよびhttp://code.google.com/p/distorm/wiki/diStorm_Internals

于 2009-05-29T04:41:55.553 に答える
6

アセンブルされ、生成されたコードと命令の両方を提供する小さなプログラムから始めます。命令アーキテクチャを使用してリファレンスを取得し、アーキテクチャリファレンスを使用して生成されたコードの一部を手動で処理します。命令は、オペランドの数が変化するinst opopopの非常にステレオタイプな構造を持っていることがわかります。あなたがする必要があるのは、命令に一致するようにコードの16進または8進表現を変換することです。少し遊んでみるとそれが明らかになります。

自動化されたそのプロセスは、逆アセンブラーの中核です。理想的には、命令構造の配列を内部的に(または、プログラムが非常に大きい場合は外部的に)構築することをお勧めします。次に、その配列をアセンブラ形式の命令に変換できます。

于 2009-05-29T04:00:27.667 に答える
4

ロード元のオペコードのテーブルが必要です。

基本的なルックアップデータ構造はトライですが、速度をあまり気にしない場合はテーブルで十分です。

基本オペコードタイプを取得するには、テーブルの一致から始めます。

レジスタ引数をデコードする方法はいくつかあります。ただし、それらのほとんどを個別に実装する必要がある十分な特殊なケースがあります。

これは教育的なものなので、ndisasmを見てください。

于 2009-05-29T04:02:55.173 に答える
2

objdumpソースをチェックアウトします-これは優れたツールであり、多くのオペコードテーブルが含まれており、そのソースは独自の逆アセンブラを作成するための優れたベースを提供できます。

于 2011-08-07T23:27:42.000 に答える