命令長決定方法と箇所
命令長を保持する場所が決まったので、今度は命令長を決定する方法と箇所を考えます。まず考えられる箇所は、命令の情報を探し出す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
とします。実装は今のところ下記の通りになります。
'命令長を取得します Public Shared Function GetCommandLength(ByVal cmd As CommandName) As Integer Return 2 End Function
現時点では、今まで実装した機械語命令長はすべて2なので単純に2を返すだけにしておきます。なお、命令長は1から数える仕様としています。そして、1番目は必ず命令を表すバイトということにしています。
※レジスタと命令が1組になっている命令は2ではなく1としてカウントします。あまりに単純すぎて、初心者の方は不安になったかもしれませんが、意外と実務ではこのように実装していきます。始めからいろいろなことを考えすぎると、読みづらく保守しにくいスパゲッティコードを生む結果になってしまいます。むろん経験をつめば、ある程度先を見越して実装することができるようになりますが、経験をつむまでは「シンプルイズベスト」を心がけてください。
これで命令長を決定できますので、SearchOpeCodeMap
メソッド内で早速使います。
'命令長設定 result.Length = GetCommandLength(result.Name) '結果を返す Return result
SearchOpeCodeMap
メソッドを使用する場所は「結果を返す一歩手前」です。理由は、命令長を判別するためには「何の命令か」を事前に決定しておかないといけないからです。何の命令か分からない状態で、命令の長さを決定することはできません。
これでVirtualCPU側の作業が一段落しましたので、ひとまずテストドライバの方の変更をすることにします。
テストドライバの変更
命令長に対応するためにはテストドライバ側の変更も必要となります。
なぜならば、今までは値のバイナリを取得&設定していましたが、これから実装するINCとDEC命令は値が必要ありません。このように、命令長の違いにより必要となるバイナリが異なりますので、変更する必要があるのです。
変更する箇所は、バイナリを取得する部分である、CmdExeButton_Click
メソッドです。 今回の変更作業は「命令長を考慮して余計なバイトを取得しない」ことですから、どこかで命令長を取得して、その値に基づいて処理をせねばなりません。
どこで命令長を取得するのかという問題は、この処理でも同じで「実行する命令が判別できた後」です。IntelCPU
オブジェクトとの違いは「値に関するバイナリを読む必要がある」という点です。ですから、この点については条件分岐で対処することにします。
これから筆者の実装例を掲載しますが、皆さんも一度自分で実装してみてください。
'指定された機械語を実行する 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
実装後は一度テストドライバをビルドしてから実行して、前回のテストドライバと同じ動きをするか試してください。同じ動きをしない場合は間違っていますので、今回の記事をもう一度始めから読んで修正してください。