ModR/Mの実装
ModR/Mはややこしいことに、Mod、レジスタ/オペコード、R/Mの3つの情報から成り立っています。手を動かしたほうが理解しやすいので、まずはModR/Mを構造体として実装します。
Public Structure ModRM 'ModR/Mの値 Private m_value As Byte 'Mod Public Property ModValue() As Byte Get Dim msk As Byte = 192 Return (Me.m_value And msk) >> 6 End Get Set(ByVal value As Byte) If value >= 0 And value < 4 Then Dim msk As Byte = 63 Dim tmp As Byte = Me.m_value And msk Me.m_value = tmp + (value << 6) Else Throw New ArgumentOutOfRangeException("必ず0以上3以下の値を指定して下さい。") End If End Set End Property 'レジスタ/オペコード Public Property RegOrOpeValue() As Byte Get Dim msk As Byte = 56 Return (Me.m_value And msk) >> 3 End Get Set(ByVal value As Byte) If value >= 0 And value < 8 Then Dim msk As Byte = 199 Dim tmp As Byte = Me.m_value And msk Me.m_value = tmp + (value << 3) Else Throw New ArgumentOutOfRangeException("必ず0以上7以下の値を指定して下さい。") End If End Set End Property 'R/M Public Property RMValue() As Byte Get Dim msk As Byte = 7 Return Me.m_value And msk End Get Set(ByVal value As Byte) If value >= 0 And value < 8 Then Dim msk As Byte = 248 Dim tmp As Byte = Me.m_value And msk Me.m_value = tmp + value Else Throw New ArgumentOutOfRangeException("必ず0以上7以下の値を指定して下さい。") End If End Set End Property Public ReadOnly Property Binary() Get Return Me.m_value End Get End Property Sub New(ByVal val As Byte) Me.m_value = val End Sub End Structure
このコードを理解するためには、ModR/Mの構造について理解する必要があります。IA-32 インテル アーキテクチャ•ソフトウェア• デベロッパーズ•マニュアル中巻のページ2-1命令フォーマット図2-1を参照してください。この図に従って、この構造体を実装しました。
つまり、先頭2ビットはMod
プロパティ、次の3ビットはRegOrOpeValue
プロパティ、最後の3ビットはRMValue
プロパティとして実装しています。このModRM
構造体も、レジスタ構造体と同じくビットごとの論理積を使用しています。
分かりやすいように、RegOrOpeValue
プロパティの実装を一例として説明します。このプロパティの実装が分かれば、他のプロパティの実装の意味も分かると思います。もし分からない場合は、Windowsの関数電卓を用いて実際に計算してみてください。なお、ビットごとの論理積についての詳しい説明については第2回を参照してください。
実装の説明
まずGet部分を説明します。1バイトの値から中間の3ビットを取り出すためには、000111000(10進数の56)と現在値でビットごとの論理積を求めます。そうすると中央の3ビットの値だけが取り出せます。
次にSet部分について説明します。始めに0~7の値しか指定できないようにチェックしています。これは3ビットのとりうる値が0~7だからです。そして、正常値(0~7)であれば、現在のレジスタ/オペコードを0に初期化しています。この方法はGet部分とは反対で、111000111(10進数の199)と現在の値でビットごとの論理積を求めることにより行います。
最後に指定された値を3ビット分左算術シフトしています。これは、レジスタ/オペコードが3~5ビット目にあるからです。
これでModR/Mの実装の完了しました。次はMUL命令の実装を進めるためにOpeCode
構造体の改良点を説明します。
OpeCode構造体の改良
今まで説明したように、MUL命令は他の命令とは命令フォーマットが違いますので、命令フォーマットを表すOpeCode
構造体も変更しなくてはなりません。最初に改良した部分を提示し、その後で説明します。
Public Structure OpeCode 'このプロパティを追加 'オペコードの次の情報 Private m_next As InfoType Public Property NextInfo() As InfoType Get Return Me.m_next End Get Set(ByVal value As InfoType) Me.m_next = value End Set End Property End Structure 'オペコードの次の情報 Public Enum InfoType Value Register End Enum
命令フォーマットの項で説明したように、機械語の命令フォーマットは、まずオペコードがあって、次に即値かModR/Mがあります。この「次の情報」を表すためにOpeCode構造体にNextInfoプロパティを追加しました。このプロパティを追加することにより、次の情報が即値なのかModR/Mなのかを判別できるようになります。次の項ではこのModR/Mのバイナリ表現を扱う方法を実装します。