SHOEISHA iD

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

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

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

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

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

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

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

各種機械後命令の修正

 前項で機械語の実行を終了したことを通知するイベントを実装しましたので、むろん今まで実装した機械語命令も修正せねばなりません。全ての命令に修正を加えているのですが、あまりにも長くなりますので、一例だけサンプルコードから抜粋して説明します。

'DIV命令の実装
Private Sub Div(ByVal ope As OpeCode)
    Dim before As ULong
    Dim value1 As ULong
    Dim after As ULong
    Dim beforeRemainder As UInteger
    Dim afterRemainder As UInteger
    Select Case ope.BitCount
        Case 8
            '値を先に用意
            before = Me.AL
            beforeRemainder = Me.AH
            Dim value As UShort
            If ope.IsHi Then
                value = ope.Value.ValueHighByte
            Else
                value = ope.Value.ValueLowByte
            End If
            value1 = value

            '剰余を算出
            Dim remainder As UShort = Me.AX Mod value

            '商を算出
            Dim tmp As UShort = Me.AX - remainder
            Dim quotient As UShort = tmp / value

            '結果をレジスタに反映する
            Me.AH = CByte(remainder)
            Me.AL = CByte(quotient)
            after = Me.AL
            afterRemainder = Me.AH
        Case 32
            '値を先に用意
            before = Me.EAX
            beforeRemainder = Me.EDX
            Dim value As UInteger = ope.Value.ValueU32
            value1 = value

            '剰余を算出
            Dim remainder As UInteger = Me.EAX Mod value

            '商を算出
            Dim tmp As UInteger = Me.AX - remainder
            Dim quotient As UInteger = tmp / value

            '結果をレジスタに反映する
            Me.EDX = CByte(remainder)
            Me.EAX = CByte(quotient)
            after = Me.EAX
            afterRemainder = Me.EDX
    End Select
    Me.OnDivExecuteCommandEnd(CommandName.Mul, before, value1, after, beforeRemainder, afterRemainder)
End Sub

 DIV命令実装と実行の項で掲載したコードと見比べてください。ローカル変数が増え、最後にイベントを発行しているのに気づいたと思います。初心者の人は一見すると複雑に見えますが原理は簡単です。イベントを発行するに当たって、必要な情報をローカル変数に保存しているだけです。DIV命令そのものの動きは変わったわけではありません。その点さえ分かれば、他の命令についても理解できると思います。一度各命令の実装を見てください。

 これで機械語命令が実行された際の情報を外部に通知できます。後は受け取る側のテストドライバを修正すれば完成です。

テストドライバの修正

 テストドライバで新しく実装したイベントを受け取るには、フォームのロードイベントでイベントハンドラを追加します。

Private Sub TestForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    'テスト対象となるIntelCpuオブジェクトを用意する
    cpu = New IntelCpu()
    AddHandler cpu.RegisterValueChanged, AddressOf RegisterValueChanged
    AddHandler cpu.FlagValueChanged, AddressOf FlagValueChanged
    AddHandler cpu.MoveCommandEnd, AddressOf MoveCommandEnd
    AddHandler cpu.CalculateCommandEnd, AddressOf CalculateCommandEnd

    'レジスタの初期値を表示
    Me.ShowEaxRegisters(New Register(cpu.EAX))
    Me.ShowEbxRegisters(New Register(cpu.EBX))
    Me.ShowEcxRegisters(New Register(cpu.ECX))
    Me.ShowEdxRegisters(New Register(cpu.EDX))

    'エラーを防止するために、レジスタが必ず選択されている状態にする。
    RegisterCombo.SelectedIndex = CInt(RegisterName.EAX)
    CmdCombo.SelectedIndex = CInt(CommandName.Mov)

    '値を見やすくするための設定
    format = New NumberFormatInfo()
    format.NumberDecimalDigits = 0
End Sub

 後はイベントを処理するためのメソッドを実装します。

'情報欄にMov命令実行内容を表示する
Private Sub MoveCommandEnd(ByVal sender As Object, ByVal e As MovCommandEndEventArgs)
    ResultLabel.Text = "値が" & e.Value.ToString("N", format) & "に初期化されました。"
End Sub

'情報欄に計算結果を表示する
Private Sub CalculateCommandEnd(ByVal sender As Object, ByVal e As CalculateCommandEndEventArgs)
    ResultLabel.Text = e.BeforeValue.ToString("N", format) & _
            " " & e.Sign.ToString() & " " & _
            e.Value.ToString("N", format) & " = " & e.AfterValue.ToString("N", format)
End Sub

 そして、RegisterValueChangedメソッドを以下のように修正します。

Private Sub RegisterValueChanged(ByVal sender As Object, ByVal e As RegisterValueChangedEventArgs)

    'レジスタの値を反映させる
    Select Case e.Gruop
        Case RegisterGruop.A
            Me.ShowEaxRegisters(e.AfterValue)
        Case RegisterGruop.B
            Me.ShowEbxRegisters(e.AfterValue)
        Case RegisterGruop.C
            Me.ShowEcxRegisters(e.AfterValue)
        Case RegisterGruop.D
            Me.ShowEdxRegisters(e.AfterValue)
    End Select

End Sub

 前回のサンプルコードと見比べてください。随分と実装が簡単になったのが分かってもらえると思います。

 これで全ての実装作業は終わりです。早速実行して色々試してください。

まとめ

 いかがでしょうか? 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」など、さまざまなカンファレンスを企画・運営しています。

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

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

メールバックナンバー

アクセスランキング

アクセスランキング