この世のCPUを食べ尽くすのだ! 第1章 第1節

~あんたCPUなんか創ってどうするのよ?! Vol.3~

2018/10/8
技術書典5 け39

第1章 第1節 ROMと同じ位置にRAMを接続する方法

まずは良くある方法から。

ROMとRAMを同じ位置に接続する方法です。

図3 ROM と RAM を同じ位置に接続する方法
図3 ROMとRAMを同じ位置に接続する方法

ここで言う同じ位置とはROMとRAMが並列に接続され、データバスとアドレスバスを共有するという意味です。CPUから見ると両者の区別は無く、同じアドレス空間を共有します。この方式はノイマン型などと呼ばれ、PCやスマートフォンで一般的な方法なので、多くの方がご存知でしょう。

このノイマン型の利点は大きく3つあります。

プログラム作成時にROMとRAMを区別する必要がない
ROMにアクセスするための専用命令や、RAMに書き込むための専用命令が不要です。表記法はCPUのアーキテクチャによって様々ですが、MOV命令やLD命令やST命令などを使って自由にROMやRAMにアクセスできます。

プログラムをROM上でもRAM上でも動作させることができる
PCやスマートフォンではHDDやフラッシュメモリやネットワークからRAM上にプログラムを読み込んで実行します。ROM上のプログラムを使うのは初期化時のみです。
高級言語との相性が良い
高級言語、特にC言語は単一のメモリ空間を前提に設計されています。そのためROMとRAMの区別がないアーキテクチャは高級言語と相性が良いのです。
例えばC言語の代表的な関数であるprintf()を考えてみましょう。
printf()関数は引数として渡された文字列の内容を画面に表示しますが、このとき引数がROMを指し示しているのかRAMを指し示しているのかを意識しません。例えばROM内に格納された文字列、つまり文字列定数を表示する場合は以下のように記述します。
printf("Hello World!");
この場合ROM内に格納された「Hello World!」という文字列の先頭アドレスがprintf()関数に渡されます。そしてprintf()関数は渡されたアドレスから順番に文字を画面に出力していき、ヌル文字が出現したところで終了します。
これは文字列がRAMに格納されている場合も全く同様です。
char s[] = "Hello World!";
printf(s);
この例では最初の行でRAM上に文字列変数sを確保し、「Hello World!」という値で初期化します。末尾にヌル文字が追加されるので、全体で13バイトの文字列変数ということになります。そして2行目ではsの先頭アドレスをprintf()関数に渡しています。printf()関数は渡されたアドレスから順番に文字を画面に出力していき、ヌル文字が出現したところで終了します。
このようにROMとRAMの区別が無いために自然にプログラムを書くことができ、かつプログラムの実行も自然に行うことができます。

図4 ノイマン型における printf() 関数
図4 ノイマン型におけるprintf()関数