はじめに
本記事はVB.NETの初歩的な記法だけを使って、簡単な機械語で動く仮想CPUの実装法を解説します(※CPUにもいろいろありますが、この記事ではIntel社が製造しているCPUを対象とします)。その過程を通じて、初心者でもバイナリプログラミングが楽しめることや、バイナリプログラミングの魅力を伝えられればと思います。前回は、仮想CPUを実装するために必要な基礎知識を解説しました。今回は、いよいよ仮想CPUをVB.NETで実装していきます。一緒に楽しみましょう。
下準備
まずは下準備をしましょう。新規プロジェクトで「VirtualCPU」という名前のクラスライブラリを作成してください。仮想CPUを実装するための準備はこれだけです。
CPUに絶対必要なもの
Intel社のCPUをシミュレートする際、実装しなくてはならないのが「レジスタ」です。まずはレジスタを実装することから始めましょう。
レジスタの実装について
前回筆者は、「EAX」「EBX」「ECX」「EDX」の4つのレジスタを使用すると述べました。そのため真っ先に、それら4つのレジスタと同名のプロパティの実装を思い浮かべるかもしれません。
しかし、IntelのCPUはレジスタが入れ子状態で定義されており、それでは駄目なのです。分かりにくいと思いますので具体例を挙げます。
例えば、EAXレジスタの値に2,359,271,448(16進数で8C9F A018)の値を代入した場合、各レジスタは次の値でなければなりません。このように、AX、AH、ALの各レジスタの値がEAXレジスタの値のサブセットとなる、といった入れ子関係が存在します。
EAX = 2,359,271,448(16進数で 8C9F A018) AX = 40,984(16進数で A018) AH = 160(16進数で A0) AL = 24(16進数で 18)
つまり、レジスタは単純にプロパティとして定義するだけでは再現できない仕組みになっています。そこで今回はRegister
構造体を定義することにします。では早速、プロジェクトに「Register.vb」ファイルを追加し、次のプログラムを入力してみましょう。
'レジスタの動きをエミュレートする構造体 Public Structure Register '共有する値 Private m_value As UInteger '32ビットレジスタの値 Public Property ValueU32() As UInteger Get Return m_value End Get Set(ByVal value As UInteger) m_value = value End Set End Property '16ビットレジスタの値 Public Property ValueU16() As UShort Get Return 0 End Get Set(ByVal value As UShort) End Set End Property '16ビットレジスタの左半分(high) Public Property ValueHighByte() As Byte Get Return 0 End Get Set(ByVal value As Byte) End Set End Property '16ビットアドレスの右半分(low) Public Property ValueLowByte() As Byte Get Return 0 End Get Set(ByVal value As Byte) End Set End Property End Structure