[PP0906] 02. 主記憶と制御装置

いよいよこれから実際のプログラムを書いていくことになります。まずは擬似プロセッサの骨格となる部分から作っていきましょう。それが主記憶(これはプロセッサの一部とはいえませんが)と制御装置です。

主記憶は簡単です。64K ワードのアドレス空間全体にメモリを配置するわけですから、ワード(int 型を使います)を要素とする 64K(65536 = 0x10000)個の配列とします。名前は memory としましょう。

int memory[0x10000];

memory は大きな配列ですので、関数の外で定義するようにした方がよいでしょう。

次にレジスタを作りましょう。PP0906 には、PC(プログラムカウンタ)、SP(スタックポインタ)、A(アキュムレータ)、X(インデックスレジスタ)という 4 本のレジスタを持ちますので、それぞれ、

int pc;
int sp;
int a;
int x;

のように変数を定義(宣言)してください。これらの変数定義は、main 関数の中でも外でもかまいません。さらに、主記憶から命令フェッチを行ったときに命令を格納するための命令レジスタも変数として定義しておきましょう。名前は ireg とします。

int ireg;

ireg の定義も、main 関数の中でも外でもかまいませんが、強いていえば、main 関数の中で定義した方がよいでしょう。さらに、レジスタではありませんが、計算した実効アドレスを格納するための変数として eaddr を定義しましょう。eaddr は main 関数の中で定義してください。

それでは、main 関数の処理を書いていきたいと思います。プロセッサというのは、単純な動作を延々と繰り返すものです。そのため、延々と繰り返すためのループを作りましょう。

for (;;)
{
}

ここで、for (;;) というのは、永久ループを作るための書き方です。永久ループというのは、for 文の中で、break などで強制的に抜け出さないかぎり、いつまででも繰り返すループのことです。今後は、ほとんどの場合、この永久ループの中に処理を追加していくことになります。特に指定が無いかぎりは for 文の中に追記するものだと考えてください。

今度は、命令フェッチの処理を追加します。命令フェッチは、メモリ上の現在の PC が指す位置から、命令を取り出すことです。したがって、次のように書きます。

ireg = memory[pc];
pc = pc + 1;

メモリからフェッチを行うときは、必ず PC を 1 進めることを忘れないでください。そうでないと、いつまでも同じところの命令を読み続けることになり、プログラムが先に進まなくなってしまいます。命令フェッチによって取り出した命令は、命令レジスタ ireg に格納します。

命令フェッチの後はデコードです。取り出した命令の値によって動作をかえる必要がありますので、switch 文を使います。とりあえず、今の時点では個々の命令は実装しませんので、switch 文の中に case はひとつもありません。

switch (ireg)
{
}

命令のデコードとは少し違うかもしれませんが、命令が -1 であれば擬似プロセッサを終了させる必要がありますので、この処理を追加しましょう。場所は、デコードの switch 文の直前がよいでしょう。

if (ireg == -1) break;

これで最低限の枠組みはできました。コンパイルができることを確認してください。なお、この連載記事では、main 関数の基本的な書き方については説明しません。説明が必要な方は入門書を読むなどしてください。

ここまでのプログラムは、コンパイルすることはできても、実行するとおそらくは異常終了してしまいます。擬似プロセッサを終了するための -1 を主記憶に書き込んでいないため、PC が増えていくと、そのうち memory の要素数より大きくなって、配列の範囲外をアクセスしてしまうからです。次回からは、この擬似プロセッサ PP0906 上で動作する簡単なプログラムを作りながら、進めていきたいと思います。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/516
このエントリーを含むはてなブックマーク