これから作るCPUはもちろんプログラムを実装することが出来る。ということでCPU作成を始める前にプログラムについての話をする。
プログラム
プログラムあるいはソフトウェアと言ったらどんなものを思い浮かべるだろうか。まず思い浮かぶのは、こんなのじゃないだろうか。
#include <stdio.h>
#define VALUE1 3
#define VALUE2 5
int main (int argc, char *argv[])
{
int a = VALUE1;
int b = VALUE2;
int sum;
sum = a + b;
printf (“sum = %d\n”, sum);
return 0;
}
上記の例はC言語というプログラミング言語のコードである。それに対し、今回作るCPUに書き込むプログラムはこんなのである。
0011 0011
0000 0101
1001 0000
とてもプログラムには見えない只の数字の羅列である。何が書いてあるか分からないと思うが、少し待ってほしい。順に説明する。
高級言語と低級言語
先に説明したC言語というのは高級言語と言われる部類になる。高級言語とは、英単語や記号などを組み合わせて命令を記述することで、人間にとって理解や記述をし易くした言語のことを言う。高級言語にはC言語以外にもBASIC、Java、C#、python、Swift等がある。
しかし、コンピュータは0と1のみで動くはずである。高級言語のような英単語を直接理解できるはずがない。コンピュータは上記のような高級言語で書かれたプログラムを直接実行しているのではなく、機械語という0と1のみで記述された言語に変換して実行している。
コンピュータが直接実行できる言語を機械語、またはマシン語と言う。機械語はちょうど上にもあるように”0011 0011”のようなコードである。
この前半の”0011”の部分はコンピュータに対する命令になっていて、この例では「次に示す値をAレジスタに転送しろ」という命令を表す。そして後半の0011が値となる。これは10進数に直すと3である。よって、“0011 0011”は「Aレジスタに3を転送しろ」という命令となる。
ここで0011という機械語の命令は、人間にとってはあまりに覚えにくい。よってこの0011に人間にとって分かりやすい名前を付ける。今だと「Aレジスタに転送しろ」だから”MOV A”という名前を付ける。これだとMOV A 0011となり、命令の意味が分かり易くなる。
このような機械語に人間に分かり易い名前をつけた言語をアセンブラとかアセンブリ言語という。またMOV Aのような命令自体をニーモニックと呼ぶ事もある。
機械語やアセンブリ言語のことを低級言語という。低級言語はとてもハードウェアに近い言語である。MOV A命令を見ても分かる通りレジスタというハードウェアを直接操作している。他にも入力やメモリといったハードを直接操作する。
低級言語というのはCPUのハードウェア部分を直接触ることのできる言語である。
ところで、この機械語やニーモニックのような命令コードはCPUの種類によって使用できる命令が変わってくる。命令コードは、CPUの使用用途に合わせてCPU毎に設計されているからだ。
CPUと命令コードは一対である。これからCPUを設計するにあたり、命令コードも設計して行く事になる。
高級言語から低級言語への変換
高級言語から低級言語への変換の話をする。今回のCPU作成ではC言語のような高級言語は実装しないため、ここからの話は余談となる。
C言語で考える。C言語は以下の手順を踏んで機械語に変換される。
この作業はコンパイラと言われるプログラムが行う。具体的に見て行くと
・プリプロセス:C言語の#で始まる#includeや#defineというプリプロセッサ命令を解釈する。
・コンパイル:C言語ソースコードをアセンブラコードに変換する。生成されたファイルの拡張子は「.s」となる。
・アセンブル:アセンブラコードを機械語コードに変換する。変換された後のファイルは「.o」という拡張子になる。oはオブジェクトファイルの意味である。
・リンク:別のファイルやライブラリファイルなど、複数のオブジェクトファイルをまとめてひとつの実行ファイルを作る場合、リンクという作業を行いオブジェクトファイルをまとめて実行ファイルを作成する。Windows用の実行ファイルなら「.exe」という拡張子になる。
コンパイラは有名なものではgccというコンパイラがある。GNUという組織が作っているコンパイラでオープンソースなので無償で利用できる。
ところで、このコンパイラを通すと機械語が生成されるのだが、機械語はCPUの種類によって様々である。なのでコンパイラを通す際、その機械語を動かしたい目的のCPUに合わせてコンパイラを選ぶ必要がある。armコア用ならarm用のコンパイラ、x86系ならx86用コンパイラ、Renesasマイコン用ならRenesas用コンパイラという様にそれぞれのCPUに合わせたコンパイラを使用する。