プログラムはなぜ動くのか!? CPU・メモリー・OSの仕組みとは!?

プログラムはなぜ動くのか – 知っておきたいプログラミングの基礎知識。

多くの著名人が推薦される同書は「知っておきたいプログラミングの基礎知識」ということで、コンピュータの本質的な内容が満載であり、IT業界で働く全ての人にとってのバイブルです。

TaNA
私も新人時代にこちらの書籍を奨められましたが、当時はいまいち理解出来ず…10年経った今改めて読み返すと腑に落ちる内容ですが、それでも一度読んだくらいでは、スラスラと理解するのは難しい。

普段業務でスクリプト言語ばかり触っていると、メモリーやCPUを意識することは少ないのですが、今回はコンピュータを根幹を成すCPU・メモリー・OSに焦点を絞って一部抜粋。

CPUとレジスタ

プログラム実行までの流れを理解する第一歩は「CPUの仕組み」を知ること。

CPUはICと呼ばれる電子部品で作られ、レジスタ・制御装置・演算装置・クロックの4つの要素から構成されますが、この中でプログラマが意識すべきなのはレジスタのみ。

POINTレジスタは処理対象となる命令やデータを格納する領域でメモリーの役割を担う!!

高水準言語で書かれたプログラムはコンパイラでマシン語に変換後、レジスタで処理されます。

ちなみにそのレジスタは大雑把に以下の7種類に分類されます。

例えばプログラムが以下のようにメモリーにロードされた場合。

レジスタの一つである プログラム・カウンタ で値(上の例では0100)が設定され、CPUが命令を実行する度にカウンタ値がインクリメント、CPUの制御装置ではカウンタ値を参照しながら、メモリーから命令を読み出して処理が実行されます。

CPUの役割

プログラムの流れにおいて、順次進行はカウンタ値が1ずつ増加するのみ、条件分岐や繰り返し処理ではアキュムレータの値を記録するフラグ・レジスタの値を参照し、ジャンプ命令を行うか判断。

ただし関数の呼び出しはジャンプ処理ではなく、特殊なマシン語で対応します。

POINT関数呼び出しは「コール命令」と「リターン命令」と呼ばれるマシン語で実行!!

コール命令では関数処理のアドレス値をプログラム・カウンタに設定する前に、関数呼び出し後に実行すべき命令のアドレス値をスタックと呼ばれるメイン・メモリーに保存しておき、リターン命令ではスタック値を読み込んで処理継続。

高水準言語で書かれた複雑なプログラムも、CPU内部の処理は以下の4種類しかありません。

4種類しかないですが、レジスタの理解は不可欠!!

メモリーの構造

メモリーの実体はメモリーICと呼ばれる電子部品であり、電源・アドレス信号・データ信号・制御信号を入出力するためのピン(ICの足)を使い、アドレスを指定することでデータの読み書きを制御。

上記例では、信号ピンD(0〜7)は7個あるので一度に8bitのデータ入出力が可能で、アドレスピンA(0〜9)は10個あるので1024通りのアドレスが指定可能です。

データの入出力はVCCに+5V、GNDに0Vの電源を繋ぎ、データ値とアドレス値を設定、WRの信号に1を指定して入力でき、出力時はアドレス値を指定し、RDの信号を1を指定することで出力可能。

配列はメモリーを利用する基本ですが、工夫を凝らしてメモリーを使う例として本書では スタック・キュー・リスト・二分探索木などの手法 が紹介されています。

OSの機能

今でこそWindowsやiOSなど当たり前に利用しているOSですが、OSが存在しなかった大昔はプログラマがあらゆる処理を自前で、しかもマシン語で作成していたらしいので、大昔のプログラマは今と比べ物にならない程、低レイヤー技術に長けていたことでしょう。

それからモニター・プログラム(プログラムをロードする機能と実行する機能)が生まれ、それに基本的な入出力を行う部分的なプログラムが追加されて初期のOSが誕生、時代は進み、ハードウェア制御プログラム、言語プロセッサ、ユーティリティが追加されて現代に至ると。

OSが動作している環境で実行されるアプリケーションは、ハードウェアを直接制御せず、OSを介して間接的にハードウェアを制御するようになっているので、変数の宣言に対するメモリ領域確保や関数の実行は、ハードウェアではなく、OSに対して作用。

OSのハードウェア制御機能は小さな関数の集合体とじて提供されており、これらの関数及び呼び出す行為を システム・コール と呼び、OSと高水準言語によってハードウェアは完全に抽象化されるため、ハードウェアを直接制御するプログラム・コードを書く必要はありません。