1. はじめに
こちらの本の第1章を読んで学んだことをまとめる
本書は、これからプログラミングを始めたい人、スキルアップを目指す初級プログラマ、そしてすべてのコンピュータユーザのために、プログラムが動作する仕組みをやさしく解き明かしたもの。説明の都合上、コンピュータのハードウェアも多々登場するが、あくまでもプログラム・ソフトウェアがテーマ。
2. CPUとは何か?
まずはプログラムの実行イメージ
➀ プログラマが、C言語などの高水準言語でプログラムを記述する
➁ プログラムをコンパイルしてマシン後のEXEファイルに変換する
➂ プログラムの起動時に、EXEファイルのコピーがメモリ上に作成される
➃ CPUが、プログラムに内容を解釈・実行する
2.1 プログラム・マシン語
プログラムとは
コンピュータに実行させる処理の順番を示すもので、命令とデータで構成される。ハードディスクなどのディスク媒体に保存されたプログラムは、メモリーにコピーされてから実行される。
マシン語とは
CPUが直接解釈できる言語。
2.2 CPUとは
このようにCPUは最終的にマシン語となったプログラムの内容を解釈して実行する装置。
構成要素
「レジスタ」…
処理対象となる命令やデータを格納する領域。1個のCPUに数個~数十個ある。
「制御装置」…
メモリー上の命令やデータをレジスタに呼び出し、命令の実行結果に応じてコンピュータを制御する。
「演算装置」…
メモリーからレジスタに呼び出されたデータを演算する。
「クロック」…
CPUが動作するタイミングとなるクロック信号を発生させる。
2.3 メモリとは
通常メモリとは、メインメモリ(主記憶)のこと。CPUと制御用ICなどを介してつながっていて、メモリーの内部に命令とデータを格納する。
また、1バイト(=8ビット)ずつにアドレス(番地)と呼ぶ番号が付いている。
メインメモリに格納されている命令やデータはパソコンの電源を切ると消える。
2.4 全体像
プログラムはレジスタを対象として記述されるから、プログラマが意識しなければならないのはレジスタだけ。
続いてレジスタを詳しく見ていく。
3. レジスタ
| レジスタの種類 | 役割 |
|---|---|
| アキュムレータ | 演算を行うデータおよび演算後のデータを格納する |
| フラグ・レジスタ | 演算処理後のCPUの状態を格納する |
| プログラム・カウンタ | 次に実行する命令が格納されたメモリーのアドレスを格納する |
| ベース・レジスタ | データ用のメモリー領域の先頭アドレスを格納する |
| インデックス・レジスタ | ベース・レジスタからの相対アドレスを格納する |
| 汎用レジスタ | 任意のデータを格納する |
| 命令レジスタ | 命令そのものを格納する |
| スタック・レジスタ | スタック領域の先頭アドレスを格納する |
3.1 アキュムレータ
具体例: 10 + 5 という計算を行う場面
動き: まず「10」というデータをアキュムレータに読み込む。次に演算装置(ALU)が「5」を加算し、計算結果である「15」をそのままアキュムレータに上書きして保持する。
3.2 フラグ・レジスタ
具体例: if (a == b) のような条件分岐(判定)を行う場面
動き: CPUは内部的に a - b の引き算を行います。もし結果が 0(つまり a と b が等しい)であれば、フラグ・レジスタ内にある「ゼロフラグ」という特定のビットを 1 にする。CPUはこのフラグの状態を見て、次にどの処理へ進むか(ジャンプするか)を決定する。

3.3 プログラム・カウンタ
具体例: プログラムの命令を上から順に実行していく場面
動き: 現在実行している命令がメモリーの 0x0100 番地にあり、その命令のサイズが4バイトだとする。CPUがその命令を読み込むと同時に、プログラム・カウンタは自動的に 0x0104 に書き換わり、「次は 0x0104 番地の命令を読めばいい」と準備をしておく。

3.4 ベース・レジスタ
具体例: array[3] のような「配列」の特定の要素にアクセスする場面
動き: 配列全体のデータが置かれているメモリーの先頭アドレス(例: 0x2000)を ベース・レジスタ に記憶させる。次に、アクセスしたい3番目の要素が先頭からどれくらい離れているか(例: 12バイト先)という相対距離を インデックス・レジスタ に記憶させる。CPUは ベース + インデックス (0x2012)を計算して、目的のデータにアクセスする。

3.5 汎用レジスタ
具体例: for (int i = 0; i < 10; i++) のようなループ処理を行う場面
動き: ループの回数をカウントする変数 i の値など、一時的に覚えておきたいデータ(キャッシュとして)を格納する。メモリーに毎回読み書きするよりも、CPU内部にある汎用レジスタを使う方が圧倒的に処理が速いため。

3.6 命令レジスタ
具体例: メモリーから命令を読み込んで、何をするか解読(デコード)する場面
動き: プログラム・カウンタが指し示すアドレスから、「加算せよ」「データを移動せよ」といったマシン語の命令データを読み込み、一時的にこの命令レジスタに格納する。制御装置はここに入ったマシン語を見て、各種ハードウェアに指示を出す。

3.7 スタック・レジスタ
具体例: ある関数から別の関数を呼び出す場面(例: main() 関数の中で print() 関数を実行する)
動き: 別の関数に処理が移る際、元の関数(main)に後で戻ってこられるように、「戻り先のアドレス」や「一時的なローカル変数」をメモリー上の「スタック」と呼ばれる領域に積み上げて退避させる。スタック・レジスタは、現在スタックに積まれているデータの「一番上(最新の場所)」のアドレスを常に指し示し続ける。



