数の単位とデータ型
1桁の2進数の数(0か1)をビットという単位で表します。そして、4ビットをニブル、8ビットをバイトと呼びます。さらに、2バイト(16ビット)をワード、4バイト(32ビット)をダブルワード、8バイト(64ビット)をクワッドワード、16バイト(128ビット)をダブルクワッドワードと呼びます。VB.NETにさまざまなデータ型が存在するのと同じで、CPUにもデータ型があると考えれば分かりやすいと思います。
Intel社のCPUの構造
VB.NETでプログラムを組む際、データを一時的に保存するには変数を使用します。ですから皆さまはデータを一時保存せずに実用的なプログラムを組めないことをよくご存知でしょう。
実はCPUもプログラマが指示した命令を実行するのに、データの一時保存場所が必要となります。その場所はレジスタと呼ばれています。Intel社のCPUの構造は大変複雑で、さまざまなレジスタが存在します。しかしこの記事では基本的には、EAX・EBX・ECX・EDX4個のレジスタしか使用しません。
レジスタについて
先ほど書いたEAX・EBX・ECX・EDXの4つのレジスタはダブルワード(32ビット)のデータを保存することができます。これはVB.NETのInteger型に該当します。ですが、CPUで常にダブルワードの数値だけを使ってプログラムを組むのは大変効率が悪いので、VB.NETと同じくCPUにも違うデータ型のレジスタがあります。それは、ワード(16ビット)のAX・BX・CX・DXの4個のレジスタと、1バイト(8ビット)のAH・AL・BH・BL・CH・CL・DH・DLの8個のレジスタがあります。なお、ワードとバイトはそれぞれVB.NETのShort型、Byte型と同じと考えてください。
ここまで読んだ読者は、私が先ほど4個のレジスタしか使用しないといったことと矛盾していると思うでしょう。しかしそれには理由があります。その理由は、最初書いた4個のダブルワード型レジスタが、ワード型レジスタとバイト型レジスタを含むからです。マニュアル上のP3-10の図3-4を参照してください。レジスタの構造が一目で分かると思います。CPUは効率性と拡張性を考えて、レジスタをこのように扱っています。
機械語
ではCPUはどうやって人間が指示する命令を処理するのでしょうか? それは0と1の羅列をCPUが解釈することにより行います。
皆さまは0と1でどうやって命令を実行するのかと疑問に思われるでしょう。筆者も始めそう感じました。その答えは、マニュアル中Bの「付録Aオペコード・マップ」に書かれています。
では早速簡単な命令を見てみましょう。一番簡単な命令はNOPの何もしない命令です。この命令はA-6ページの表A-2で調べると1列目の10行目にあります。1列目は0、10行目は9と書かれていますので、16進表記で90という数値がCPUに送られてくると何もしないことになります。この例で分かることが一つあります。それは、すべての数値にあらかじめ意味が定義されていることです。0と1の羅列に意味を定義し、定められた動作をすることによりCPUは動いているのです。この0と1の羅列を機械(CPU)が直接理解できる言葉という意味で機械語(マシンワード)と呼びます。本記事では、VB.NETでこの機械語を理解できる仮想CPUを作ります。
どうです? ワクワクするでしょ。
まとめ
今回は導入編として、仮想CPUを作るための基礎だけを解説しました。次回からは実際に仮想CPUの実装を解説しますので楽しみにしてください。
バイナリプログラミングのテクニックは、実際の業務で直接使うことはあまりないと思います。しかしながら、バイナリプログラミングをすることで培った知識は、デバッグをする際にも役立ちますし、自然と高級言語をより上手く扱えるようになります。難しいと身構えずに気楽に遊んで技術力を向上させましょう。
この記事を通じて1人でも多くの人が、VB.NETを使ってバイナリプログラミングすることの楽しみに目覚めていただければ幸いです。
