SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

VB.NETで学ぶ機械語の基礎

VB.NETで仮想CPUを作ろう (10)
- MLU命令の実装とModR/Mについて

VB.NETで学ぶ機械語の基礎 第10回

  • X ポスト
  • このエントリーをはてなブックマークに追加

ModR/Mのバイナリを扱う方法

 MUL命令は幸いほとんどが固定値なので、ModR/Mの操作方法は簡単です。MUL命令はModが11、レジスタ/オペコードが100なので、後はR/Mだけを導出すればよいのです。R/Mにはソースオペランドとなるレジスタを表す値を設定します。

 このレジスタの値は必要なビット毎に分かれています。まず8ビット(バイト)のレジスタは、AL・CL・DL・BL・AH・CH・DH・BHの順に0~7までの値が割り振られています。次に32ビット(ダブルワード)のレジスタはEAX・ECX・EDX・EBXの順に0~3までの値が割り振られています。

注意事項

この記事では、16ビットのレジスタは32ビットCPUではMUL命令で使用できないので省略しています。また、32ビットのレジスタについても全てのレジスタを書いているわけではありません。注意してください。

 以上を踏まえて、レジスタの名前から数値を返すメソッドと、その逆に数値からレジスタ名を割り出すメソッドを実装します。

レジスタに割り当てられた番号を操作するメソッド
'指定した8ビットレジスタに対応する値を返す
Public Shared Function GetRegisterByteModRMValue(ByVal reg As RegisterName) As Byte
    Select Case reg
        Case RegisterName.AL
            Return 0
        Case RegisterName.CL
            Return 1
        Case RegisterName.DL
            Return 2
        Case RegisterName.BL
            Return 3
        Case RegisterName.AH
            Return 4
        Case RegisterName.CH
            Return 5
        Case RegisterName.DH
            Return 6
        Case RegisterName.BH
            Return 7
        Case Else
            Throw New ArgumentOutOfRangeException("このメソッドは" & reg & "には対応していません。")
    End Select
End Function

'指定した32ビットレジスタに対応する値を返す
Public Shared Function GetRegister32ModRMValue(ByVal reg As RegisterName) As UInteger
    Select Case reg
        Case RegisterName.EAX
            Return 0
        Case RegisterName.ECX
            Return 1
        Case RegisterName.EDX
            Return 2
        Case RegisterName.EBX
            Return 3
        Case Else

            Throw New ArgumentOutOfRangeException("このメソッドは" & reg & "には対応していません。")
    End Select
End Function

'ModR/Mで指定された1バイトレジスタの名称を判別する
Private Shared Function GetRegister8Name(ByVal value As Byte) As RegisterName
    Select Case value
        Case 0
            Return RegisterName.AL
        Case 1
            Return RegisterName.CL
        Case 2
            Return RegisterName.DL
        Case 3
            Return RegisterName.BL
        Case 4
            Return RegisterName.AH
        Case 5
            Return RegisterName.CH
        Case 6
            Return RegisterName.DH
        Case 7
            Return RegisterName.BH
        Case Else
            Throw New ArgumentOutOfRangeException("必ず0以上7以下の値を指定して下さい。")
    End Select
End Function

'ModR/Mで指定されたダブルワードレジスタの名称を判別する
Private Shared Function GetRegister32Name(ByVal value As Byte) As RegisterName
    Select Case value
        Case 0
            Return RegisterName.EAX
        Case 1
            Return RegisterName.ECX
        Case 2
            Return RegisterName.EDX
        Case 3
            Return RegisterName.EBX
        Case Else
            Throw New ArgumentOutOfRangeException("必ず0以上3以下の値を指定して下さい。")
    End Select
End Function

 これらメソッドの実装内容は説明不要だと思いますので省略します。これでR/Mの設定を行えるようになりましたので、ModR/Mのバイナリを導出するメソッドを実装できます。これから筆者の実装例を提示しますが、皆さんも一度自分で実装してみてください。

ModR/Mのバイナリを返すメソッド
'ModR/Mのバイナリを取得する
Public Shared Function GetModRMBinary(ByVal cmd As CommandName, ByVal reg As RegisterName) As Byte
    Dim result As ModRM = New ModRM(0)
    result.ModValue = 3
    Select Case cmd
        Case CommandName.Mul
            result.RegOrOpeValue = 4
            Dim bit As Byte = GetRegisterBit(reg)
            If bit = 8 Then
                result.RMValue = GetRegisterByteModRMValue(reg)
            ElseIf bit = 32 Then
                result.RMValue = GetRegister32ModRMValue(reg)
            Else
                Throw New ArgumentOutOfRangeException("MULでは16ビットのレジスタを指定できません。")
            End If
        Case Else
            Throw New ArgumentOutOfRangeException(cmd & "はサポートしていません。")

    End Select
    Return result.Binary
End Function

'指定したレジスタが対応しているビット数を返す。
Public Shared Function GetRegisterBit(ByVal reg As RegisterName) As Byte
    If reg >= RegisterName.EAX And reg <= RegisterName.EDX Then
        Return 32
    ElseIf reg >= RegisterName.AX And reg <= RegisterName.DX Then
        Return 16
    Else
        Return 8
    End If
End Function

 ではプログラムの説明をします。今回はメモリを扱わないのでModValue(Mod部)は3で固定、MUL命令は先ほど説明したようにレジスタ/オペコード部が100で固定なのでRegOrOpeValueプロパティに4を設定しています。後は指定されたレジスタのビット数をGetRegisterBitメソッドで取得し、先ほど実装したレジスタに対応する数値を返すメソッドを使って、RMValue(R/M)プロパティに値を設定するだけです。これで基本的なパーツが実装できましたので、次項から順を追って実装していきます。

次のページ
MUL命令実装手順

修正履歴

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
VB.NETで学ぶ機械語の基礎連載記事一覧

もっと読む

この記事の著者

インドリ(インドリ)

分析・設計・実装なんでもありのフリーエンジニア。ブログ「無差別に技術をついばむ鳥(http://indori.blog32.fc2.com/)」の作者です。アドバイザーをしたり、システム開発したり、情報処理技術を研究したりと色々しています。座右の銘は温故知新で、新旧関係なく必要だと考えたものは全て学...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3149 2010/04/27 12:03

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング