2012-02-17 4 views
3

私は、x86アーキテクチャ用の命令のサブセット用のシミュレータを実装したいと考えています。バイナリが与えられたら、それを逆アセンブルして命令上のシミュレーションを実行したいと思います。そのためには、制御命令、算術命令または論理命令のいずれであるかを決定するために命令の特定のビットを見る必要があり、それに基づいて、残りのビットを調べることによって演算のパラメータを導出しなければならない。これを実装するための明白かつ苦痛な方法の1つは、ネストされたif-else/switch-caseステートメントを使用することです。誰かがこれを実装するためのより良い方法を提案できますか?x86のサブセット用のシミュレータの実装

+1

基本的にswitch-caseステートメントが必要ですが、それほど必要ではありません。ルックアップテーブルにチェックインします。バイトを取得し、そのバイトの値のハンドラを呼び出し、ハンドラがオペランドを読み込んでリターンし、繰り返します。 – ssube

答えて

3

ルックアップテーブルは、おそらくstd::mapの形式で使用します。

+0

何百万回も繰り返し実行できるものについては、 'map'よりもパフォーマンスに少し興味があると思います。少なくとも、ハッシュテーブルが望ましいでしょうが、それでもおそらく最善の選択ではありません。 – StilesCrisis

1

翻訳の出力をキャッシュする場合、ネストされたif/elseタイプの構文を使用すると問題はありません。シミュレーションを実行している場合は、プログラム内のすべての静的命令から動的命令が比較的少なくなります。したがって、パフォーマンスの最適な最適化は、変換の出力をキャッシュし、動的命令が実行されたときに再利用することです。最終的にキャッシュがいっぱいになるので、新しいエントリについてはクリアする必要があります。しかし、最初に翻訳を行う本当に高速な方法を考え出すのではなく、何らかの形で翻訳をキャッシュする方が意味があります。

例として、QEMUは、パフォーマンスに最適化されたさまざまなターゲットをサポートするエミュレータです。あなたは、彼らがここにx86命令を変換する方法を見ることができます。

https://github.com/qemu/QEMU/blob/master/target-i386/translate.c#L4076

QEMUは、すべての命令のためにこれをしなかった場合のパフォーマンスが非常に遅くなります。しかし、結果をキャッシュしてから、命令が最初に翻訳されるときに複雑なケース・ステートメントがあることはそれほど重要ではありません。

1

x86エミュレータのソースを見れば、すでに完全に書かれています。

ここでは、試してみてください一つだ:http://www.dosbox.com/wiki/BuildingDOSBox#1._Grab_the_source

はこれがうまくいかない場合は、私に教えてください。そこから選ぶべきたくさんがあります。

通常、エミュレータを使用すると、オペコードのスイッチが移動する方法の1つになると思います。もう1つの良いアプローチは、命令の最初のバイトに対応する256エントリの関数ポインタの配列です。これは、巨大なスイッチやブロックよりも少し離れています。もちろん、必要に応じて関数を再利用することもできます。