SHOEISHA iD

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

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

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

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

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

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

命令長決定方法と箇所

 命令長を保持する場所が決まったので、今度は命令長を決定する方法と箇所を考えます。まず考えられる箇所は、命令の情報を探し出すSearchOpeCodeMapです。ですから最も単純な実装方法は、次のようになります。

SearchOpeCodeMapの抜粋
SearchOpeCodeMapの抜粋
'行と列から命令を割り出す
Select Case row
    Case 0
        Select Case col
            Case 4
                result.Name = CommandName.Add
                result.Destination = RegisterName.AL
                result.BitCount = 8
                result.Length = 2

 しかしこの方法では、各命令ごとにLengthプロパティの値を設定せねばなりませんし、柔軟性がありません。例えば、命令長だけを知りたい時、SearchOpeCodeMapメソッドを使用するのでは、効率性も悪く、準備に手間がかかります。ですから、解決方法は別のメソッドを用意する形式を採用します。 命令長を返すメソッド名は、分かりやすいようにGetCommandLengthとします。実装は今のところ下記の通りになります。

現時点のGetCommandLengthメソッド
'命令長を取得します
Public Shared Function GetCommandLength(ByVal cmd As CommandName) As Integer
    Return 2
End Function

 現時点では、今まで実装した機械語命令長はすべて2なので単純に2を返すだけにしておきます。なお、命令長は1から数える仕様としています。そして、1番目は必ず命令を表すバイトということにしています。

※レジスタと命令が1組になっている命令は2ではなく1としてカウントします。

 あまりに単純すぎて、初心者の方は不安になったかもしれませんが、意外と実務ではこのように実装していきます。始めからいろいろなことを考えすぎると、読みづらく保守しにくいスパゲッティコードを生む結果になってしまいます。むろん経験をつめば、ある程度先を見越して実装することができるようになりますが、経験をつむまでは「シンプルイズベスト」を心がけてください。

 これで命令長を決定できますので、SearchOpeCodeMapメソッド内で早速使います。

SearchOpeCodeMapの抜粋
'命令長設定
result.Length = GetCommandLength(result.Name)

'結果を返す
Return result

 SearchOpeCodeMapメソッドを使用する場所は「結果を返す一歩手前」です。理由は、命令長を判別するためには「何の命令か」を事前に決定しておかないといけないからです。何の命令か分からない状態で、命令の長さを決定することはできません。

 これでVirtualCPU側の作業が一段落しましたので、ひとまずテストドライバの方の変更をすることにします。

テストドライバの変更

 命令長に対応するためにはテストドライバ側の変更も必要となります。

 なぜならば、今までは値のバイナリを取得&設定していましたが、これから実装するINCとDEC命令は値が必要ありません。このように、命令長の違いにより必要となるバイナリが異なりますので、変更する必要があるのです。

 変更する箇所は、バイナリを取得する部分である、CmdExeButton_Clickメソッドです。 今回の変更作業は「命令長を考慮して余計なバイトを取得しない」ことですから、どこかで命令長を取得して、その値に基づいて処理をせねばなりません。

 どこで命令長を取得するのかという問題は、この処理でも同じで「実行する命令が判別できた後」です。IntelCPUオブジェクトとの違いは「値に関するバイナリを読む必要がある」という点です。ですから、この点については条件分岐で対処することにします。

 これから筆者の実装例を掲載しますが、皆さんも一度自分で実装してみてください。

SearchOpeCodeMapの抜粋
'指定された機械語を実行する
Private Sub CmdExeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)  _
        Handles CmdExeButton.Click
        
    Dim binary(1) As Byte

    '指定された命令を実行する
    If Me.GetCmmandAndRegisterBinay(binary) = False Then
        Return
    End If

    '命令長を取得
    Dim length As Integer = IntelCpu.GetCommandLength(Me.CmdCombo.SelectedIndex)

    '命令長が1の場合は値に関するバイナリは必要ない
    If length > 1 Then
        If Me.GetValueBinary(binary) = True Then
            Me.ExecuteCommand(binary)
        End If
    Else
        Me.ExecuteCommand(binary)
    End If
End Sub

 実装後は一度テストドライバをビルドしてから実行して、前回のテストドライバと同じ動きをするか試してください。同じ動きをしない場合は間違っていますので、今回の記事をもう一度始めから読んで修正してください。

次のページ
INC命令実装

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

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング