SHOEISHA iD

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

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

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

VB.NETで仮想CPUを作ろう (9) - INC命令&DEC命令の実装と命令長

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

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

テストドライバ側の対応

 テストドライバがまずやるべきことは、INC命令とDEC命令を指定できるようにすることです。もっと具体的に言うと、CmdComboコントロールのアイテムにIncとDecを指定せねばなりません。プロパティウインドウでItemsプロパティにIncとDecを追加してください。

 次にするべきことは命令の実行結果を表示することです。INCとDEC命令の実行結果を表示するには、RegisterValueChangedメソッドを変更します。結果を表示するべき命令が増えて、メソッドが読みにくくなってきましたので、今回リファクタリングしてINC命令とDEC命令に対応しました。まずはそのコードを掲載し、後でその内容を説明します。

リファクタリング後の新しい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

    '情報欄を更新する
    Select Case CmdCombo.SelectedIndex
        Case CommandName.Mov
            If Me.RegisterCombo.SelectedIndex = RegisterName.EAX Then
                ResultLabel.Text = "値が" & e.AfterValue.ValueU32.ToString() & "に初期化されました。"
            ElseIf Me.RegisterCombo.SelectedIndex = RegisterName.AL Then
                ResultLabel.Text = "値が" & e.AfterValue.ValueLowByte.ToString() & "に初期化されました。"
            End If
        Case CommandName.Add, CommandName.Subtract, CommandName.Inc, CommandName.Dec

            '符号を設定
            Dim sign As String = ""
            If CmdCombo.SelectedIndex = CommandName.Add OrElse _
                CmdCombo.SelectedIndex = CommandName.Inc Then
                sign = " + "
            ElseIf CmdCombo.SelectedIndex = CommandName.Subtract OrElse _
                CmdCombo.SelectedIndex = CommandName.Dec Then
                sign = " - "
            End If

            '値を設定
            Dim value As String = ""
            If CmdCombo.SelectedIndex = CommandName.Add OrElse _
                CmdCombo.SelectedIndex = CommandName.Subtract Then
                value = UInteger.Parse(ValueText.Text).ToString("N", Me.format)
            ElseIf CmdCombo.SelectedIndex = CommandName.Inc OrElse _
                CmdCombo.SelectedIndex = CommandName.Dec Then
                value = "1"
            End If

            '結果を設定
            Dim result As String = ""
            Select Case e.BitCount
                Case 32
                    result = e.AfterValue.ValueU32.ToString()
                Case 16
                    result = e.AfterValue.ValueU16.ToString()
                Case 8
                    If e.IsHi Then
                        result = e.AfterValue.ValueHighByte.ToString()
                    Else
                        result = e.AfterValue.ValueLowByte.ToString()
                    End If
            End Select

            '計算式を表示
            ResultLabel.Text = e.BeforeValue.ValueU32.ToString() & _
                    sign & value & " = " & result
    End Select
End Sub

 前回のソースと見比べてください。ずいぶん変わったと思います。しかし、行っていることは前回とあまり変わりませんし、これから丁寧に説明しますので、安心して読み進めてください。

 大まかな方針として、筆者は「同じ目的を持ったコードを固める」ことにしました。前回も少しお話しましたが、人間はコードが散らばると理解しにくくなります。それに、まとめて考えた方がコードを理解しやすくなります。ですから、目的ごとにコードを集めました。

 その結果、このメソッドのコードは「レジスタの値を反映する」処理と「情報欄を更新する」処理の2つに大別できるようになりました。レジスタの値を反映する処理については解説済みなので、もう一方の「情報欄を更新する」処理を説明します。

 この処理はさらに「符号を設定」「値を設定」「結果を設定」「計算式を設定」と4つに分かれています。初心者の方は難しく見えるかもしれませんが、これから書くイメージで捉えれば簡単です。

元の値(BeforeValue) +-などの符号(sign) 値(value)= 結果(result)

 先ほど書いた4個の処理は、それぞれの変数の値を決定するだけのものであり、難しいことはしていません。一見複雑に見える処理も、このようにイメージで捉えれば簡単になるケースが実務でも多いので、なるべくコードをイメージの塊で考えるようにしてみてください。そうするとコードを読む力がぐんとアップします。

 実行していろいろと試してください。実行すればINC命令とDEC命令が正しく実装されていることが確認できます。しかし、操作勝手に問題があるのが分かると思います。

よりよいテスト

 現状のテストドライバでまず気になるのが「値欄」です。INC命令とDEC命令は値が1に固定されているので、値欄に値が入力できる状態では余計な混乱を生みます。まずはその点を改善するために、CmdComboコントロールのSelectedIndexChangedイベントに次にコードを書き込みます。

テスト作業を手助けするための処置
'選択した命令にあわせて値欄の表示を操作する
Private Sub CmdCombo_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CmdCombo.SelectedIndexChanged
    If Me.CmdCombo.SelectedIndex = CommandName.Inc OrElse _
        Me.CmdCombo.SelectedIndex = CommandName.Dec Then
        Me.ValueText.Enabled = False
    Else
        Me.ValueText.Enabled = True
    End If
End Sub

 これでINC命令とDEC命令のテスト時に余計な混乱を生まなくて済みます。一度実行してみてください。INC命令とDEC命令を選択した際には値欄が編集できなくなって、テスト作業が分かりやすくなったことが確認できます。

 次に筆者が気になったのは、限界値テストのやりにくさです。限界値テストというのは、システム仕様の最大値を超えた場合どうなるか、最小値未満の値を指定したらどうなるかなどをテストすることです。今回の場合、0の状態でインクリメントしたらどうなるかと、32ビット値の最大値を超えた場合どうなのかをテストしなければなりません。しかし、現状では非常にやりにくいです。そこで、限界値を値入力欄に設定できる用にフォームにメニューを追加しました。

 画面を掲載しますのでそれとサンプルコードを参考にしてメニューを追加してください。

新しいテストドライバの画面
画像

 そして、追加したメニューのクリックイベントに次のコードをコーディングします。

最大値を値入力欄に設定するコード
'最大値を設定する
Private Sub MaxValueMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MaxValueMenuItem.Click
    If Me.RegisterCombo.Text(0) = "E" Then
        Me.ValueText.Text = UInteger.MaxValue.ToString()
    ElseIf RegisterCombo.Text(1) = "X" Then
        Me.ValueText.Text = UShort.MaxValue.ToString()
    Else
        Me.ValueText.Text = Byte.MaxValue.ToString()
    End If
End Sub}

 これで限界値のテストが行いやすくなりました。このようにテストの際には、素早く正確に行うための準備をしておくことをお勧めします。

まとめ

 いかがでしょうか? 今回は仮想CPUを作る上で避けられない命令長の扱いについて解説しました。

 また、この記事の読者が実務で活躍することを祈って、限界値テストや実務で培ったコーディングのノウハウを散りばめました。プロとアマの違いは実のところ意外と少なく、心がけ次第でプロにもアマにもなることが伝われば幸いです。

 何のプロでもそうだと思うのですが、プロとは「他者への気配り」がその明暗を分けると筆者は思います。お客様に対して親切にするのは勿論のこと、一緒に仕事をする同僚や、未来に自分のコード保守する人まで気を配ることができれば、その人は立派なプロと呼ばれることでしょう。

 次回は、今までで一番手強いMUL(乗算)命令の実装を紹介します。この命令を実装することにより、IntelCPUにレジスタが複数あることの意味が見えてくるでしょう。お楽しみに。

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

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

もっと読む

この記事の著者

インドリ(インドリ)

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

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

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

この記事をシェア

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング