SHOEISHA iD

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

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

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

VB.NETで仮想CPUを作ろう (11)
- DIV命令の実装とイベント設計について

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

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

ダウンロード VirtualCPU11.zip (317.2 KB)

GetModRMBinaryメソッド修正

 DIV命令の説明で述べましたが、MUL命令とDIV命令の違いはModR/Mです。ですから、GetModRMBinaryメソッドでその違いを表現することになります。これから筆者の実装例を提示しますので、MUL命令とDIV命令を分ける部分に注目して下さい。

'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 CommandName.Div
            result.RegOrOpeValue = 5
            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("DIVでは16ビットのレジスタを指定できません。")
            End If
        Case Else
            Throw New ArgumentOutOfRangeException(cmd & "はサポートしていません。")
    End Select
    Return result.Binary
End Function

 一見したところ前回と変わりませんが、重要な違いがあります。それはRegOrOpeValueプロパティの設定箇所です。よく見ると、MUL命令ではRegOrOpeValueプロパティの値が4、DIV命令の場合RegOrOpeValueプロパティの値に5が設定していることに気づくと思います。これがMUL命令とDIV命令の違いです。

 これで命令を完全に判別する材料が揃いましたので、次項にてIntelCpuオブジェクトがMUL命令とDIV命令を判別できるようにします。

命令の判別法

 MUL命令とDIV命令を判別するには、バイナリの解析機能であるAnalyzeBinaryメソッドを修正します。後で内容を解説しますので、まずは筆者の実装例を見て下さい。

'読み込まれたバイナリ値を解析して実行する命令を特定します。
Public Sub AnalyzeBinary()
    Dim binary As Byte
    While binarys.Count <> 0

        '指定されている命令とレジスタを決定
        binary = binarys.Dequeue()
        Dim ope As OpeCode = SearchOpeCodeMap(binary)

        '値を導出
        Dim modrm As ModRM
        If ope.NextInfo = InfoType.Value Then
            '即値をバイナリから取得
            If ope.BitCount = 32 Then
                Dim values(3) As Byte
                For i As Integer = 0 To 3
                    values(i) = Me.binarys.Dequeue()
                Next

                'Intelはリトルエンディアンなので値を逆にする
                values = GetLittleEndianValue(values)

                '取得したバイト配列からダブルワードの値を構築
                Dim value As UInteger = ConvertValues(values)
                ope.Value = New Register(value)
            Else
                ope.Value = New Register(binarys.Dequeue(), ope.IsHi)
            End If
        ElseIf ope.NextInfo = InfoType.Register Then
            'レジスタから値を取得
            modrm = New ModRM(Me.binarys.Dequeue())
            If ope.BitCount = 32 Then
                Dim reg As RegisterName = GetRegister32Name(ModRM.RMValue)
                ope.Value = New Register(Me.GetRegister32Value(reg))
            ElseIf ope.BitCount = 8 Then
                Dim reg As RegisterName = GetRegister8Name(modrm.RMValue)
                ope.Value = New Register(Me.GetRegisterByteValue(reg))
            End If
        End If

        '命令が確定していないのならば決定
        If ope.State <> OpeCodeState.Fixed Then
            Select Case modrm.RegOrOpeValue
                Case 4
                    ope.Name = CommandName.Mul
                Case 5
                    ope.Name = CommandName.Div
                Case Else
                    Throw New ArgumentOutOfRangeException("ModR/MのRegOrOpeValueフィールドには" & modrm.RegOrOpeValue & "を指定しないで下さい")
            End Select
            ope.State = OpeCodeState.Fixed
        End If

        '実行する命令を記憶
        cmds.Enqueue(ope)
    End While
End Sub

 ポイントは「命令が確定していないのならば決定」の部分です。ここまでの処理で、SearchOpeCodeMapメソッド内で、ope変数のStateプロパティにFixed以外の値が設定されています。そこで、この部分では、ModR/MのRegOrOpeValueプロパティの値で命令の判別を行っています。

 これでオペコードのバイナリ値が同じ、MUL命令とDIV命令の判別ができるようになりました。後はDIV命令を実装して実行するだけです。

次のページ
DIV命令実装と実行

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

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

もっと読む

この記事の著者

インドリ(インドリ)

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

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

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

この記事をシェア

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング