SHOEISHA iD

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

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

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

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

VB.NETで仮想CPUを作ろう (5) - CPUの基礎動作の実装

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

GetBinaryメソッドの実装

 IntelCpuクラスがSearchOpeCodeMapメソッドでバイナリを解釈することを先ほど解説しました。ですがここで1つ問題があります。それは、IntelCpuクラスを利用する時、いちいちIntelマニュアルを見る必要があるということです。これでは不便なので、実行したい命令と対象レジスタを指定したら対応するバイナリが返すGetBinaryメソッドを実装します。

'指定された命令と対象レジスタから指定するべきバイナリを導出する
Public Shared Function GetBinary(ByVal cmd As CommandName, _
    ByVal reg As RegisterName) As Byte

    Dim result As Byte

    'オペコードマップの行と列の値を決定
    Select Case cmd
        Case CommandName.Mov
            result = 11 << 4
            Select Case reg
                Case RegisterName.EAX, RegisterName.AX
                    result += 8
                Case RegisterName.EBX, RegisterName.BX
                    result += 11
                Case RegisterName.ECX, RegisterName.CX
                    result += 9
                Case RegisterName.EDX, RegisterName.DX
                    result += 10
                Case RegisterName.AH
                    result += 4
                Case RegisterName.AL
                    result += 0
                Case RegisterName.BH
                    result += 7
                Case RegisterName.BL
                    result += 3
                Case RegisterName.CH
                    result += 5
                Case RegisterName.CL
                    result += 1
                Case RegisterName.DH
                    result += 6
                Case RegisterName.DL
                    result += 2
                Case Else
                    Throw New ArgumentException("命令" & cmd & "は" & _
                        reg & "レジスタをサポートしておりません。")
            End Select
    End Select

    '結果を返す
    Return result
End Function

 Mov命令の実装はまだ取り上げていませんが、何かしら命令がないと分からないのでMov命令をいち早く実装しました。このメソッドがしていることは単純です。ただ命令とレジスタに対応する数値を返しているだけです。

DivisionValueメソッドの実装

 IntelCpuクラスを使用する上で次に問題になるのが、ダブルワードの値を1バイトに分解する必要があるということです。このクラスは仕様上、1バイトごとに解釈しているので、UIntger型の値を直接送るわけにはいきません。なぜならばCPUは命令も値もすべてをバイト列で解釈しているためです。ですからこのメソッドが必要となります。実装を掲載します。

'ダブルワードの値をバイト列に分割します
Public Shared Function DivisionValue(ByVal value As UInteger) As Byte()
    Dim result(3) As Byte
    result(0) = (value And &HFF000000) >> 24
    result(1) = (value And &HFF0000) >> 16
    result(2) = (value And &HFF00) >> 8
    result(3) = value And &HFF
    Return result
End Function

 このメソッドがしているのは、自分が必要のない場所を0と指定するビットごとのAnd論理積です。第3回でも説明しましたが、必要な桁を1に不必要な桁を0にしてこの演算をすれば、必要な桁の値だけが残ります。

 次に算術右シフトをしています。これは算術左シフトとは逆に、一つシフトするごとに値を1/2づつ減少させます。これは、1バイトの値が必要だからです。ですから、上記のresult(0)の計算では、4バイト目の値を24ビット算術右シフトして1バイトに値を縮小しています。

 実際に計算してみます。例えば2進数の「10011100 00000000」(16進数で「9C00」、10進数で「39936」)を右へ8ビットシフトすると、2進数で「10011100」(16進数で「9C」、10進数で「156」)となります。値が1/2の8乗、つまり1/256になり、1バイト分の値に縮小できていることも分かります(ここでは下位から2バイト目の値を取得)。

2進数の 10011100 00000000
2進数の          10011100 ←8ビット右シフト

 この2つの算術を行うことにより、ダブルワードの値を4個のバイトにできます。この説明を読んでよくわからない方は、この記事の例の数値を変えてWindows付属の関数電卓で何度か計算してみてください。そうすればよく分かります。

まとめ

 いかがだったでしょうか? 筆者としては今までで一番面白い回だと思います。実装を通じてIntelのCPU動作のイメージが少しずつ浮かびあがってきたのではないでしょうか。

 ぜひ一度、自分自身でサンプルプログラムを参考にプログラミングをしてみてください。今までブラックボックスだったCPUの中身が少し見えてくるでしょう。バイナリプログラミングの魅力はそこにあります。この記事を通じて、CPUの理解の助けになれば幸いです。

 次回からは機械語命令を実装していきます。お楽しみに。

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

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

もっと読む

この記事の著者

インドリ(インドリ)

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

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

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

この記事をシェア

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

イベント

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

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

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

メールバックナンバー