私はこれを何度もやってきて、これを続けています。あなたの主な目的がアセンブラーを読むことでなく書くことであるこの場合、私はこれが当てはまると思います。
独自の逆アセンブラーを作成します。次に大きい逆アセンブラを作成するためではなく、これは厳密にあなたのためです。目標は、命令セットを学ぶことです。新しいプラットフォームでアセンブラーを学習しているかどうかは、以前知っていたプラットフォームのアセンブラーを思い出します。ほんの数行のコードから始めて、たとえばレジスタを追加し、バイナリ出力を逆アセンブルすることと、入力側にますます複雑な命令を追加することとの間にピンポンを実行します。
1)特定のプロセッサの命令セットを学ぶ
2)上記のプロセッサ用にアセンブルでコードを記述する方法のニュアンスを学び、すべての命令のすべてのオペコードビットを小刻みに動かせるようにする
3)その命令セットを使用して生計を立てているほとんどのエンジニアよりも、命令セットをよりよく学ぶ
あなたの場合、いくつかの問題がありますが、通常ARM命令セットから始めることをお勧めします。今日出荷されているARMベースの製品は他のどの製品よりも多くなっています(x86コンピュータを含む)。しかし、現在ARMを使用していて、スタートアップコードやARMを認識している他のルーチンを作成するのに十分なアセンブラーを知らない可能性は、実行しようとしていることに役立つ場合とそうでない場合があります。ARMが最初に重要になる2番目の理由は、命令の長さが固定サイズで整列されているためです。x86のような可変長命令を分解することは、最初のプロジェクトとして悪夢になる可能性があり、ここでの目標は、研究プロジェクトを作成しないように命令セットを学ぶことです。3番目のARMはよくできた命令セットであり、レジスターは同等に作成され、個々の特別なニュアンスはありません。
したがって、どのプロセッサから始めたいかを理解する必要があります。まずmsp430またはARM、次にARMが最初または2番目、次にx86の混乱をお勧めします。どのプラットフォームを使用する場合でも、使用する価値のあるプラットフォームには、命令セットとオペコード(機械語のビットとバイト)のエンコードを含むデータシートまたはプログラマーリファレンスマニュアルがベンダーから無料で提供されています。コンパイラーが何をするか、またコンパイラーが苦労する必要のないコードをどのように書くかを学ぶために、いくつかの命令セットを理解し、各最適化を行う各コンパイラーで各命令セットに同じ高レベルのコードがどのように実装されるかを確認するのは良いことです。設定。コードを最適化したくはなく、1つのコンパイラ/プラットフォームでは改善されたが、他のコンパイラ/プラットフォームでは改善されたことがわかるだけです。
ああ、可変長の命令セットを逆アセンブルするために、単に最初から始めて、ARMのように4バイトワードごとに、またはmsp430のように2バイトごとに線形にメモリを逆アセンブルするのではなく(msp430には可変長命令がありますが、割り込みベクトルテーブルのエントリポイントから開始すると、メモリを直線的に移動します)。可変長の場合、ベクトルテーブルまたはプロセッサの起動方法に関する知識に基づいてエントリポイントを見つけ、コードを実行順に追跡する必要があります。使用されているバイト数を知るには、各命令を完全にデコードする必要があります。その後、命令が無条件分岐でない場合は、その命令の次のバイトが別の命令であると想定します。また、可能なすべての分岐アドレスを格納し、それらがより多くの命令の開始バイトアドレスであると想定する必要があります。一度成功したとき、バイナリを何度か通過しました。エントリポイントから始めて、そのバイトを命令の開始としてマークし、無条件分岐に到達するまでメモリを介して線形にデコードしました。すべての分岐ターゲットは、命令の開始アドレスとしてタグ付けされました。新しいブランチターゲットが見つからなくなるまで、バイナリを何度も通過しました。いつでも3バイトの命令を見つけたが、何らかの理由で2番目のバイトに命令の先頭としてタグ付けした場合は、問題があります。コードが高レベルのコンパイラーによって生成された場合、コンパイラーが何か悪しくない限り、これは起こらないはずです。コードに手書きのアセンブラ(古いアーケードゲームなど)が含まれている場合、条件付き分岐が発生し、r0 = 0の後にゼロでない場合はジャンプが続くなど、決して発生しない可能性があります。続行するには、バイナリから手動で編集する必要がある場合があります。私の想定しているあなたの当面の目標はx86になると思いますが、問題はないと思います。
x86がターゲットの場合、mingw32はWindowsでgccツールを使用する簡単な方法です。そうでない場合は、mingw32とmsysは、binutilsとgccソースからクロスコンパイラを生成するための優れたプラットフォームです(通常は非常に簡単です)。mingw32には、大幅に高速なプログラムのようなcygwinに比べていくつかの利点があり、cygwin dllの地獄を回避できます。gccとbinutilsを使用すると、Cまたはアセンブラーで記述してコードを逆アセンブルできます。また、3つのうちいずれか1つまたはすべてを実行する方法を示すWebページが読める数よりも多くなっています。可変長の命令セットでこれを行う場合は、逆アセンブラを含むツールセットを使用することを強くお勧めします。たとえばx86用のサードパーティの逆アセンブラは、正しく逆アセンブルされているかどうか本当にわからないため、使用するのが難しいでしょう。これの一部はオペレーティングシステムにも依存します。逆アセンブラがより正確な作業を実行できるように、データからの情報マーキング指示を含むバイナリ形式にモジュールをコンパイルすることが目標です。この主な目的の他の選択肢は、検査のためにアセンブラーに直接コンパイルできるツールを用意し、バイナリ形式にコンパイルすると同じ命令が作成されることを期待することです。
あなたの質問への短い(大丈夫少し短いER)答え。逆アセンブラを記述して、命令セットを学習します。ARMのようなRISCyで簡単に習得できるものから始めます。1つの命令セットがわかったら、多くの場合数時間で、3番目の命令セットを使用すると、構文がデータシート/リファレンスマニュアルを使用してコードをすぐに書き始めることができます。使用に値するすべてのプロセッサには、オペコードのビットおよびバイトまでの命令を説明するデータシートまたはリファレンスマニュアルがあります。ARMのようなRISCプロセッサとx86のようなCISCについて、違いを感じ取れるように十分に学びます。2つの命令に対する3つのオペランド命令など。高レベルのコードを調整すると、複数のプロセッサ用にコンパイルして、出力を比較します。あなたが学ぶ最も重要なことは、高レベルのコードがどれほど上手く書かれていても、コンパイラの品質と、行われた最適化の選択が実際の命令に大きな違いをもたらすということです。llvmとgcc(binutilsを使用)をお勧めします。どちらも作成できません。優れたコードですが、それらはマルチプラットフォームとマルチターゲットであり、どちらもオプティマイザを備えています。どちらも無料で、さまざまなターゲットプロセッサのソースからクロスコンパイラを簡単に構築できます。