SHOEISHA iD

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

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

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

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

VB.NETで仮想CPUを作ろう (6) - MOV命令の実装

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

Mov命令の実装

 AnalyzeBinaryメソッドで御膳立てされていますので、Mov命令の実装はとても簡単です。各レジスタに指定された値を設定するだけです。

'Mov命令の実装
Private Sub Mov(ByVal cmd As OpeCode)
    Select Case cmd.Destination
        Case RegisterName.EAX
            Me.EAX = cmd.Value.ValueU32
        Case RegisterName.EBX
            Me.EBX = cmd.Value.ValueU32
        Case RegisterName.ECX
            Me.ECX = cmd.Value.ValueU32
        Case RegisterName.EDX
            Me.EDX = cmd.Value.ValueU32
        Case RegisterName.AX
            Me.AX = cmd.Value.ValueU16
        Case RegisterName.BX
            Me.BX = cmd.Value.ValueU16
        Case RegisterName.CX
            Me.CX = cmd.Value.ValueU16
        Case RegisterName.DX
            Me.DX = cmd.Value.ValueU16
        Case RegisterName.AH
            Me.AH = cmd.Value.ValueHighByte
        Case RegisterName.AL
            Me.AL = cmd.Value.ValueLowByte
        Case RegisterName.BH
            Me.BH = cmd.Value.ValueHighByte
        Case RegisterName.BL
            Me.BL = cmd.Value.ValueLowByte
        Case RegisterName.CH
            Me.CH = cmd.Value.ValueHighByte
        Case RegisterName.CL
            Me.CL = cmd.Value.ValueLowByte
        Case RegisterName.DH
            Me.DH = cmd.Value.ValueHighByte
        Case RegisterName.DL
            Me.DL = cmd.Value.ValueLowByte
    End Select
End Sub

 このプログラムを見たら分かると思いますが、レジスタのビット数にさえ注意を払えばとても簡単です。Mov命令の様な単純な機械語はそこへ辿りつくまで大変ですが、辿りつけばとても簡単なのです。

 後はテストドライバがこの機械語を使用するように改良するだけです。

テストドライバの変更

 Mov命令の実装が済みましたので、後はテストドライバでそれを使うようにするだけです。次のプログラムを追加してください。

'Mov命令を実行する
Private Sub MoveDataButton_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MoveDataButton.Click

    'レジスタとコピーする値を決定
    Dim binary(1) As Byte
    Dim name As RegisterName = RegisterCombo.SelectedIndex
    binary(0) = IntelCpu.GetBinary(CommandName.Mov, _
        RegisterCombo.SelectedIndex)

    'レジスタのビット数に応じてコピーする値を用意する
    If name < RegisterName.AH Then
        ReDim Preserve binary(4)
        Dim value As UInteger

        'エラーチェック
        If name < RegisterName.AX Then
            If UInteger.TryParse(RegisterText.Text, value) = False Then
                MessageBox.Show("0~" & UInteger.MaxValue.ToString() _
                    & "までの数値を入力してください。", _
                    "入力エラー", _
                    MessageBoxButtons.OK, _
                    MessageBoxIcon.Error)
                RegisterText.Focus()
                Exit Sub
            End If
        Else
            If UShort.TryParse(RegisterText.Text, value) = False Then
                MessageBox.Show("0~" & UShort.MaxValue.ToString() & _
                "までの数値を入力してください。", _
                "入力エラー", _
                MessageBoxButtons.OK, _
                MessageBoxIcon.Error)
                RegisterText.Focus()
                Exit Sub
            End If
        End If

        '値を分解して保存
        Dim values As Byte() = IntelCpu.DivisionValue(value)
        values = IntelCpu.GetLittleEndianValue(values)
        For i As Integer = 0 To 3
            binary(i + 1) = values(i)
        Next

    Else '1バイト(8ビット)レジスタの場合
        Dim value As Byte

        'エラーチェック
        If Byte.TryParse(RegisterText.Text, value) = True Then
            binary(1) = value
        Else
            MessageBox.Show("0~" & Byte.MaxValue.ToString() & _
                "までの数値を入力してください。", _
                "入力エラー", _
                MessageBoxButtons.OK, _
                MessageBoxIcon.Error)
            RegisterText.Focus()
            Exit Sub
        End If
    End If

    '用意したバイナリを送ってMov命令を実行する
    Me.cpu.ReadBinary(binary)
    Me.cpu.AnalyzeBinary()
    Me.cpu.ExecuteCommand()

End Sub

 初心者の方はプログラムの行数に圧倒されてしまったかもしれませんが、簡単な処理の集まりで、大まかに分けると3つだけです。これから丁寧に解説しますので安心して読み進めてください。

 このプログラムのポイントはバイナリを用意してIntelCpuオブジェクトへ渡すという点です。今までの記事を思い出してください。CPUは0と1のバイナリしか理解しないので、すべての情報をバイナリに変換する必要があります。このクリックイベントではそれを行っているだけです。上から順に解説します。

 1つ目の処理ではMov命令であることと、対象となるレジスタを指定するバイナリを決定しています。やっていることは単純そのもので、画面で指定したレジスタを判別してから、前回実装したIntelCpu.GetBinaryを実行して対応するバイナリを取得しているだけです。

 2つ目の処理ではコピーする値を決定しています。この処理はレジスタのビット数によって異なります。なぜならば1バイト(8ビット)のレジスタの場合、特に値を加工する必要がないからです。こちらの方は説明の必要がないと思いますので、もう一つのコードブロック(IF文のTrueコードブロック)について説明します。

一部抜粋
If name < RegisterName.AH Then
  'Trueコードブロック
Else
  'Falseコードブロック

 Trueブロックでは、まず初めに値のエラーチェックをしています。1ワード(16ビット)レジスタの場合はUShort型、ダブルワード(32ビット)レジスタの場合はUInteger型として正しい値が入力されているかチェックしています。このチェックが正しければ次へ処理を進めています。次はコピーする値を分解しています。なぜこのようなプログラムが必要なのかと言うと、バイナリをバイト配列としてIntelCpuオブジェクトに渡すからです。詳しい説明は前回書いていますので参照してください。

 3つ目の処理では、用意したバイナリを送ってMov命令を実行しているだけです。つまり、CPUの基礎動作である、命令読み込み命令解析命令実行を順番に指定しているだけなのです。

 これでドライバの準備は完了です。実行してみてください。対象となるレジスタに任意の値を設定できるはずです。

まとめ

 いかがでしたでしょうか? 今回の記事を読めば、機械語の命令を実装することは意外と難しくないことが分かっていただけると思います。

 これは何も機械語の実装の話だけではありません。物事はなんでもそうです。プログラミングは実のところ、大半は対象を分析するまでが難しいのです。IT業界の人は仕様が大事だとよく聞くと思います。それはこのことを指しています。実装は勿論大事ですが、設計をうまくすることにより成否の大部分が決まってしまうのです。

 この記事を通じて、初心者の方もプログラミングを難しいと身構える必要がないことが伝われば幸いです。一人でも多くの人が、プログラミングを楽しいと感じ、バイナリプログラミングにチャレンジしてくれるよう筆者は願っています。

 次回は簡単な四則演算に関する機械語を実装します。お楽しみに。

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
VB.NETで学ぶ機械語の基礎連載記事一覧

もっと読む

この記事の著者

インドリ(インドリ)

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

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

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

この記事をシェア

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

イベント

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

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

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

メールバックナンバー