SearchOpeCodeMapメソッドの解説
このメソッドを理解するためには、CPUと機械語の基礎を復習しなければなりません。
機械語は0と1のバイナリであり、1バイトで命令を表現します。その数値にはあからじめIntelが意味を持たせており、これでCPUは命令を判別しています。実際どの数値がどの命令なのかは、IA-32 インテル アーキテクチャー・ソフトウェア・デベロッパーズ・マニュアル、中巻 B: 命令セット・リファレンス N-ZのA-6とA-7ページに書かれています。
ですから機械語を解析するには、人間がこの表を探す行為をシミュレートする必要があります。それがこのSearchOpeCodeMapメソッドです。
'オペコードマップを検索し、実行する命令と対象となるレジスタを探索する。 Private Shared Function SearchOpeCodeMap(ByVal binary As Byte) _ As OpeCode Dim result As OpeCode = New OpeCode() '指定されている命令を特定するために行と列を導出 Dim row As Byte = CByte((binary And &HF0) >> 4) Dim col As Byte = CByte(binary And &HF) '行と列から命令を割り出す '結果を返す Return result End Function
このプログラムの一番大事なところはこの部分です。
'指定されている命令を特定するために行と列を導出 Dim row As Byte = CByte((binary And &HF0) >> 4) Dim col As Byte = CByte(binary And &HF)
命令は1バイトで表現されており、ニプル(4ビット)に分解することで命令を指定しています。そのため、まずは引数で渡された1バイトの値を2つのニプル値へ分解する必要があります。この2つの二プルは、A-6とA-7ページの表の行と列を表します。
分解する方法は、ビットごとの論理積を求めることにより行います。ビットごとの論理積についておさらいすると、要らないビットは0、必要なビットは1にして求めます。より詳しく知りたい方は、『VB.NETで仮想CPUを作ろう (2) - レジスタの実装』を参照してください。この部分が分かればこのメソッドの実装は簡単です。
Dim result As OpeCode = New OpeCode()
後は命令の情報を記憶するOpeCode構造体に見つかった命令の情報を設定するだけです。
リトルエンディアンとビッグエンディアン
CPUがメモリへ2バイト以上のデータを保存する方法を大別すると、リトルエンディアンとビッグエンディアンの2つの方式があります。上位の桁からメモリに保存する方式をビックエンディアン(big endian)といい、逆に下位の桁から保存する方式をリトルエンディアン(little endian)と言います。
分かりにくいので例を挙げます。例えば、「10進数の37872」(16進数の93F0)をメモリへ保存する場合、図1のように保存します。

この図でリトルエンディアンのイメージがつかめると思います。この動作を実装したのが次のメソッドです。
'値の並びを逆にします。 Public Shared Function GetLittleEndianValue(ByVal values() As Byte) _ As Byte() Dim result(3) As Byte For i As Integer = 3 To 0 Step -1 result(3 - i) = values(i) Next Return result End Function
