ハードウェア レジスタに直接アクセスできたとしても、メモリの代わりにレジスタを使用するという決定にコードをラップすると、はるかに遅くなります。
パフォーマンスを得るには、パフォーマンスを事前に設計する必要があります。
いくつかの例。
すべてのトラップを設定して、仮想メモリ空間を離れるコードをキャッチすることにより、x86 VM を準備します。コードを直接実行し、エミュレートせずに分岐して実行します。コードがデバイスなどと通信するためにメモリ/I/Oスペースから到達すると、それをトラップし、そのデバイスまたは到達していたものをエミュレートしてから、制御をプログラムに戻します。コードがプロセッサに依存している場合は非常に高速に実行され、I/O に依存している場合は遅くなりますが、各命令をエミュレートするほど遅くはありません。
静的バイナリ変換。実行する前にコードを逆アセンブルして変換します。たとえば、命令 0x34,0x2E は .c ファイルで ascii に変わります。
アル ^= 0x2E; =0の; cf=0; sf=アル
理想的には、大量のデッド コードの削除を実行します (次の命令がフラグも変更する場合は、ここでは変更しないなど)。あとはコンパイラのオプティマイザに任せます。この方法でエミュレーターよりもパフォーマンスを向上させることができます。パフォーマンスの向上は、コードをどれだけ最適化できるかによって異なります。新しいプログラムであるため、ハードウェア上で実行され、メモリとすべてが登録されるため、プロセッサにバインドされたコードは VM よりも遅くなります。場合によっては、メモリをシミュレートしたため、メモリ/io をトラップする例外を処理するプロセッサに対処する必要はありません。コードでアクセスしますが、それでもコストがかかり、とにかくシミュレートされたデバイスを呼び出すため、そこに節約はありません。
sbt に似た動的変換ですが、実行時にこれを行います。たとえば、10 進アルファと言う他のプロセッサで x86 コードをシミュレートするときにこれが行われると聞きました。コードは x86 命令からネイティブ アルファ命令にゆっくりと変更されるため、次回はx86 命令をエミュレートする代わりに、alpha 命令を直接実行します。コードを実行するたびに、プログラムはより速く実行されます。
または、エミュレーターを再設計して、実行の観点からより効率的にすることもできます。たとえば、MAME でエミュレートされたプロセッサを見てください。コードの可読性と保守性は、パフォーマンスのために犠牲にされています。それが重要であると書かれているとき、今日のマルチコア ギガヘルツ プロセッサでは、1.5 GHz 6502 または 3 GHz z80 をエミュレートするのにそれほど苦労する必要はありません。テーブル内の次のオペコードを調べて、命令のフラグ計算の一部またはすべてをエミュレートしないことを決定するのと同じくらい簡単なことで、顕著なブーストが得られます。
要するに、プログラムの実行時に x86 ハードウェア レジスタ、Ax、BX などを使用して AX、BX などのレジスタをエミュレートすることに関心がある場合、それを行う唯一の効率的な方法は、命令を実際に実行することであり、実行して実行することではありません。デバッガーのシングル ステップのようにトラップしますが、VM 空間から出ないようにしながら、長い一連の命令を実行します。これを行うにはさまざまな方法があり、パフォーマンスの結果はさまざまであり、パフォーマンス効率の高いエミュレーターよりも高速になるわけではありません。これにより、プロセッサをプログラムに一致させることが制限されます。効率的なコードと非常に優れたコンパイラ (優れたオプティマイザ) を使用してレジスタをエミュレートすると、ハードウェアを実行中のプログラムに合わせる必要がないという点で、妥当なパフォーマンスと移植性が得られます。