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命令の実装が終わりDIV命令をテストドライバで実行できるようになりました。しかしながら、その結果を表示する部分がありません。それにMUL命令についても結果が表示されていません。この理由は、筆者がイベントの設計を変えようと考えていたからです。

 現在はRegisterValueChangedメソッドで全て対応しておりますが、本来イベントは一つの処理をする方が望ましいです。つまり、IntelCpuを利用する側が工夫するのではなく、IntelCpu側で利用する側の利便性を図るのがいいのです。そこで筆者は新しいイベントをいくつか考えました。

 イベント設計で重要なことは「選択性」と「柔軟性」です。もしIntelCpuが何らかのイベントを前提として動作するのならば、利用する側の負担が大きすぎます。それに、何らかの前提を設けてしまうとIntelCpuが非常に使い辛いものとなります。その2つの性質を実現する為には.NETのオブジェクト指向機能をフル活用します。

 イベントを設計するに当たって今まで実装してきた命令を改めて考えてみました。その結果MOV命令と算術命令に分かれていることに気づきました。そこで筆者は2つのイベントオブジェクトを作りました。

Public Class ExecuteCommandEventArgs
    Inherits EventArgs

    '実行されたコマンドの名前
    Private m_name As CommandName
    Public Overridable ReadOnly Property Name() As CommandName
        Get
            Return m_name
        End Get
    End Property

    '必ず実行した命令を指定してインスタンスを生成するようにします
    Public Sub New(ByVal name As CommandName)
        Me.m_name = name
    End Sub

End Class


Public Class MovCommandEndEventArgs

    Inherits ExecuteCommandEventArgs

    '変更後の値
    Private m_value As UInteger
    Public Property Value() As UInteger
        Get
            Return Me.m_value
        End Get
        Set(ByVal value As UInteger)
            Me.m_value = value
        End Set
    End Property

    '必ず値を指定して、インスタンスを生成するようにします。
    Public Sub New(ByVal value As UInteger)
        MyBase.New(CommandName.Mov)
        Me.m_value = value
    End Sub

End Class

'算術系命令が終了したことを表すイベントの情報
Public Class CalculateCommandEndEventArgs
    Inherits ExecuteCommandEventArgs

    '変更後の値
    Private m_after As ULong
    Public Property AfterValue() As ULong
        Get
            Return Me.m_after
        End Get
        Set(ByVal value As ULong)
            Me.m_after = value
        End Set
    End Property

    '指定した値
    Private m_value As ULong
    Public Property Value() As ULong
        Get
            Return Me.m_value
        End Get
        Set(ByVal value As ULong)
            Me.m_value = value
        End Set
    End Property

    '変更前の値
    Private m_before As ULong
    Public Property BeforeValue() As ULong
        Get
            Return Me.m_before
        End Get
        Set(ByVal value As ULong)
            Me.m_before = value
        End Set
    End Property

    '符号
    Private m_sign As Char
    Public ReadOnly Property Sign() As Char
        Get
            Return Me.m_sign
        End Get
    End Property

    '必ず、実行した命令・更新前の値・指定する値(加算値など)・更新後の値の四つの情報を指定して、インスタンスを生成するようにします。
    Public Sub New(ByVal name As CommandName, ByVal beforeValue As ULong, ByVal value As ULong, ByVal afterValue As ULong)
        MyBase.New(name)
        Me.m_after = afterValue
        Me.m_value = value
        Me.m_before = beforeValue
        Select Case name
            Case CommandName.Add
                Me.m_sign = "+"
            Case CommandName.Inc
                Me.m_sign = "+"
            Case CommandName.Subtract
                Me.m_sign = "-"
            Case CommandName.Dec
                Me.m_sign = "-"
            Case CommandName.Mul
                Me.m_sign = "*"
            Case CommandName.Div
                Me.m_sign = "/"
        End Select
    End Sub

End Class

'DIV命令が終了したことを表すイベントの情報
Public Class DivCommandEventArgs
    Inherits CalculateCommandEndEventArgs

    '変更前の剰余
    Private m_beforeRemainder As UInteger
    Public Property BeforeRemainder() As UInteger
        Get
            Return m_beforeRemainder
        End Get
        Set(ByVal value As UInteger)
            m_beforeRemainder = value
        End Set
    End Property

    '変更後の剰余
    Private m_afterRemainder As UInteger
    Public Property AfterRemainder() As UInteger
        Get
            Return m_afterRemainder
        End Get
        Set(ByVal value As UInteger)
            m_afterRemainder = value
        End Set
    End Property

    '必ず実行した命令を指定してインスタンスを生成するようにします
    Public Sub New(ByVal name As CommandName, _
    ByVal beforeValue As ULong, ByVal value As ULong, ByVal afterValue As ULong, _
        ByVal beforeRemainder As UInteger, ByVal afterRemainder As UInteger)
        MyBase.New(CommandName.Div, beforeValue, value, afterValue)
        Me.m_beforeRemainder = beforeRemainder
        Me.m_afterRemainder = afterRemainder
    End Sub

End Class


'汎用の機械語命令実行完了イベント
Public Event ExecuteCommandEnd(ByVal sender As Object, ByVal e As ExecuteCommandEventArgs)

'機械語命令の実行が完了したことを通知する
Private Sub OnExecuteCommandEnd(ByVal name As CommandName)
    Dim e As ExecuteCommandEventArgs = New ExecuteCommandEventArgs(name)
    RaiseEvent ExecuteCommandEnd(Me, e)
End Sub

'MOV命令実行完了イベント
Public Event MoveCommandEnd(ByVal sender As Object, ByVal e As MovCommandEndEventArgs)

'MOV命令の実行が完了したことを通知する
Private Sub OnMovCommandEnd(ByVal value As UInteger)
    Dim e As MovCommandEndEventArgs = New MovCommandEndEventArgs(value)
    RaiseEvent MoveCommandEnd(Me, e)
End Sub

'計算命令実行完了イベント
Public Event CalculateCommandEnd(ByVal sender As Object, ByVal e As CalculateCommandEndEventArgs)

'計算命令の実行が完了したことを通知する
Private Sub OnCalculateExecuteCommandEnd(ByVal name As CommandName, ByVal beforeValue As ULong, ByVal value As ULong, ByVal afterValue As ULong)
    Dim e As CalculateCommandEndEventArgs = New CalculateCommandEndEventArgs(name, beforeValue, value, afterValue)
    RaiseEvent CalculateCommandEnd(Me, e)
End Sub

'DIV命令の実行が完了したことを通知する
Private Sub OnDivExecuteCommandEnd(ByVal name As CommandName, _
ByVal beforeQuotient As UInteger, ByVal value As ULong, ByVal afterQuotient As UInteger, _
    ByVal beforeRemainder As UInteger, ByVal afterRemainder As UInteger)

    Dim e As DivCommandEventArgs = New DivCommandEventArgs(name, beforeQuotient, value, afterQuotient, beforeRemainder, afterRemainder)
    RaiseEvent CalculateCommandEnd(Me, e)

End Sub

 まずこれらのオブジェクトを実装するに当たって気をつけたことは「利用側にレジスタを意識させない」ということです。今まではRegisterValueChangedイベントでレジスタの役割や実行した命令などを考えつつ実装しました。しかし、本来オブジェクトはそれを利用する側に前提知識を強いてはなりません。前提知識を強いると生産効率が落ちて、何のためにオブジェクト指向でプログラミングしているのか分からなくなります。

 次に考えたのは「共通部分を継承させる」ということです。MOV命令以外は算術系の命令であって、なるべく一つのオブジェクトで処理できるようにしなくてはイベント数が多くなり、利用する側が大変です。そこで、共通概念を考えて算術系のイベントオブジェクトwを実装し、唯一DIV命令は継承オブジェクトを作ることにしました。そうすることで、利用側が柔軟に利用できるようになります。

 なお、筆者がExecuteCommandEventArgsを実装したわけは、「とにかく機械語の実行が終わったタイミングが知りたい」時があると考えたからです。それにIntelCpuオブジェクトは他にも違う種類のイベントが実装していますから、機械語命令を実行したという共通概念をまとめた方が利便性が高くなると考えたのです。

 実際の開発では、こういった判断はそのときのシステムの性質を考えて判断することになります。従って「何でもまとめればいい」というわけでもありません。その使い分けについては経験を積めば判断できるようになります。

次のページ
各種機械後命令の修正

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

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング