SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

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

VB.NETで仮想CPUを作ろう (4) - テストドライバの改良

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

ダウンロード VirtualCPU4.zip (213.5 KB)

RegisterValueChangedEventArgsクラスの定義

 イベント駆動型プログラミングでは、何の情報が発生するのかを考えることから始めます。今回の目的は「レジスタの変更を自動的に知りたい」ですから、レジスタの値が変更される時、何の情報が必要になるかを考えます。

 筆者が必要だと考えたのは、値が変更されたレジスタの「種類」「名前」「ビット数」「変更後の数値」の4個でした。これらの情報を扱えるようにRegisterValueChangedEventArgsクラスを定義しました。

 コードは次のとおりです。

Public Class RegisterValueChangedEventArgs
    Inherits EventArgs

    '更新を容易にするための情報
    Private m_gruop As RegisterGruop
    Public Property Gruop() As RegisterGruop
        Get
            Return Me.m_gruop
        End Get
        Set(ByVal value As RegisterGruop)
            Me.m_gruop = value
        End Set
    End Property

    'どのレジスタの値が変更されたのか表します
    Private m_name As RegisterName
    Public Property Name()
        Get
            Return m_name
        End Get
        Set(ByVal value)
            m_name = value
        End Set
    End Property

    '現在どのビット数の値を扱っているのかわかった方がいいです
    Private m_bit As Byte
    Public Property BitCount() As Byte
        Get
            Return m_bit
        End Get
        Set(ByVal value As Byte)
            m_bit = value
        End Set
    End Property

    'レジスタが入れ子状態になっているので必要です
    Private m_val As Register
    Public Property Value() As Register
        Get
            Return m_val
        End Get
        Set(ByVal value As Register)
            m_val = value
        End Set
    End Property

    '値が変更されたレジスタの名前、レジスタのビット数、
    '値を指定してインスタンスを生成します。
    Sub New(ByVal group As RegisterGruop, ByVal target As RegisterName, _
            ByVal bitCount As Byte, ByVal value As Register)
        Me.m_gruop = group
        Me.m_name = target
        Me.m_bit = bitCount
        Me.m_val = value
    End Sub
End Class

'レジスタを表す列挙体
Public Enum RegisterName
    EAX
    EBX
    ECX
    EDX
    AX
    BX
    CX
    DX
    AH
    AL
    BH
    BL
    CH
    CL
    DH
    DL
End Enum

'レジスタの種類
Public Enum RegisterGruop
    A
    B
    C
    D
End Enum

 RegisterValueChangedEventArgsの定義を解説します。GruopプロパティとBitCountプロパティについては実際に使っているところを見た方が早いので解説を後にし、RegisterNameプロパティとValueプロパティを解説します。

 RegisterNameプロパティがなぜString型でないのか疑問に思う方は多いでしょう。ですが実のところ、この方がミスが少なくて効率がいいのです。それはミスタイプが減らせるからです。文字列ではEAXをXXAなどと打ち間違ってもコンパイルできてしまいます。一方、列挙体ではエラーが発生するので、間違ったことがすぐ分かり大変便利です。それに加えて、開発環境のコード補完機能を利用している人は入力の効率がよくなる上にミスもなくなります。このような場面では、列挙体は便利なので大いに活用しましょう。

 ValueプロパティについてもUIntegerUShortByteなどの値型ではなくてレジスタ構造体であることが気になると思います。なぜこのように実装したのかと言うとレジスタが入れ子状態になっているからです。前回のテストドライバを実行して、1つのレジスタの値を変更したら複数の値が更新されたはずです。ですから、単純な値型では実現できないのでレジスタ構造体で値を指定するように実装しました。

 これでRegisterValueChangedEventArgsクラスの定義を終えたので実際に使います。実装する場所はIntelCpuクラス内です。

イベント発動

 まずはIntelCpuクラスにイベントを定義します。

'イベント
Public Event RegisterValueChanged(ByVal sender As Object, _
    ByVal e As RegisterValueChangedEventArgs)

'レジスタの値が変更されたことを通知する
Private Sub OnRegisterValueChanged(ByVal gruop As RegisterGruop, _
    ByVal name As RegisterName, _
    ByVal bitCount As Byte, ByVal value As Register)
    Dim e As RegisterValueChangedEventArgs = _
        New RegisterValueChangedEventArgs(gruop, name, bitCount, value)
    RaiseEvent RegisterValueChanged(Me, e)
End Sub

 これでレジスタの値が変更されたことを外部に通知できます。

 次にイベント発生場所を決めて、そこでOnRegisterValueChangedメソッドを使用します。


Private m_eax As Register
Public Property EAX() As UInteger
    Get
        Return Me.m_eax.ValueU32
    End Get
    Set(ByVal value As UInteger)
        Me.m_eax.ValueU32 = value
        Me.OnRegisterValueChanged(RegisterGruop.A, _
            RegisterName.EAX, 32, Me.m_eax)
    End Set
End Property

Public Property AX() As UShort
    Get
        Return Me.m_eax.ValueU16
    End Get
    Set(ByVal value As UShort)
        Me.m_eax.ValueU16 = value
        Me.OnRegisterValueChanged(RegisterGruop.A, _
            RegisterName.AX, 16, Me.m_eax)
    End Set
End Property

Public Property AH() As Byte
    Get
        Return Me.m_eax.ValueHighByte
    End Get
    Set(ByVal value As Byte)
        Me.m_eax.ValueHighByte = value
        Me.OnRegisterValueChanged(RegisterGruop.A, _
            RegisterName.AH, 8, Me.m_eax)
    End Set
End Property

Public Property AL() As Byte
    Get
        Return Me.m_eax.ValueLowByte
    End Get
    Set(ByVal value As Byte)
        Me.m_eax.ValueLowByte = value
        Me.OnRegisterValueChanged(RegisterGruop.A, _
            RegisterName.AL, 8, Me.m_eax)
    End Set
End Property

 このコードを参考に、すべての他のレジスタ関連のプロパティを実装してください(具体的な実装例は添付のサンプルコードを参照のこと)。これでIntelCpuクラスを使用しているオブジェクトに通知をすることができます。後は受け取る側の準備をするだけです。

次のページ
テストドライバ側の実装

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

VB.NETで学ぶ機械語の基礎連載記事一覧

もっと読む

この記事の著者

インドリ(インドリ)

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

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2836 2010/04/27 12:01

イベント

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

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

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

メールバックナンバー