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のバイナリ表現を扱う方法を実装します。
