2 コンピューターの仕組み

2.1 コンピューターの基本構成

コンピューターは複雑な装置であるが,図1のような機能の 集まりに分解できる2.それぞれの機能(装置)は,制御信号線とデータ信号線で 接続されている.そこを,0と1のパルスの信号が信じられないくらい高速でかつ調和を取っ て流れ,全体としてコンピューターが動作する.大量の信号がひとつも間違いなく伝送され るのは驚きである.この信号線は人間で言えば神経のようなものである.

コンピューターの基本構成は図1に示したとおりであるが, 制御装置と演算装置,記憶装置,入力装置, 出力装置を五大装置と呼ぶ.それぞれは,次のような働きがある.

制御装置
主記憶装置(メインメモリー)に格納されているプログラム(命 令)を受け取り,それを解読し,電気信号に変え,各装置に指 令を出す.
演算装置
主記憶装置(メインメモリー)に格納されているデータを受け 取り,制御装置の指令に従い,それを加工(処理)する.
記憶装置
記憶装置は,主記憶装置と補助記憶装置がある.
主記憶装置
命令とデータからなるプログラムを格納する.
補助記憶装置
主記憶装置には容量に制限があるので,それを越えるも のをここに格納する.また,主記憶装置は電源を切ると, データが失われるので,半永久的に残したい場合,補助記 憶装置に格納する.ハードディスクやCD-ROMがこれに当た る.
入力装置
コンピューターの外部からデータを取り込む装置である.キー ボードやマウス等がこれに当たる.
出力装置
主記憶装置に格納されているデータをコンピューター外部に 出力する装置である.ディスプレイやプリンター等がこれに当 たる.

主記憶装置(メインメモリー)は略して,メモリーと呼ばれることが多い.この講義でもメ モリーといえば,主記憶装置(メインメモリー)を指す.パソコンの広告を見ると「メモリー 512Mbyte搭載」とか書いてある.これがまさにメモリーの大きさを示している.

これらのなかで,制御装置と演算装置をまとめて中央制御装置(CPU:Central Processing Unit)と言う.とくに,これらを一つのチップにまとめたものを MPU(Micro Processing Unit) と言う.Intel社のPentiumやAMD社のAthlon,IBM社のPowerPCなどがMPUである.世 間一般ではMPUとCPUはほとんど同義語として使われるので,本講義では全てCPUに統一す る.その方が諸君もなじみ深いであろう.

1では,入力装置と出力装置は分けたが,ひとつで2つの機 能を果たすものもある.例えば,LANカードがそれにあたる.

図 1: コンピューターの基本構成
\includegraphics[keepaspectratio, scale=1.0]{figure/comp_5_equipments.eps}

2.2 メモリーとCPU

ここで,コンピューターを構成する最小の部品を考える.コンピューターはCPUとメイン メモリーで動作する.メインメモリーにプログラムを格納して,CPUとデータの受け渡し を行い,データを処理することができる.図2のようなも のである.ここに書いているデータバスとかアドレスバスについては,後で説明する.

プログラマーは,メモリーの内容をある程度自由に変更ができる.そのようなこと から,メモリーを意識してプログラムを作成することが重要である.アセンブラー言語を使うと なるとCPUについても意識が必要であろうが,C言語ではそこまで要求しない.諸君は,メ モリーを意識しろ!!!

図 2: もっとも原始的なコンピューター.バスの矢印は情報の流れを示す.
\includegraphics[keepaspectratio, scale=1.0]{figure/CPU_memory_with_bus.eps}


2.3 メインメモリーのモデル

メインメモリーのハードウェアーの構造については,ここではどうでも良い.それよりか, メインメモリーのモデルを理解することが重要である.

メインメモリーの役割は,命令とデータからなるプログラムを記憶することである.記憶 する内容は,0と1のビットパターンのみである.なぜならば,プログラムは全て,0と1の 数字で表せ,二進数で表現可能であるからである.コンピューター内部では,データも命 令も全て0と1の二進数で表現している.命令も二進数である;どうだ,驚いたか.ここで は,この二進数のビットパターンを格納するメモリーについて学習する.

プログラムという情報は記憶するだけでは全く役に立たない.記憶した内容を取り出せて 初めて,活用ができる.また,格納できる情報がひとつでは全く役に立たない.多くの情 報が格納でき,必要なときにいつでも取り出すことができる装置がメモリーである.

メモリーは大量の情報を格納し,その中の任意の情報を取り出すことができる.そのため に,メモリーには記憶する場所毎に住所が決められている.この住所のことをアドレス (address)と言い,整数の番地がふってある.諸君が使っているパソコンのアドレス は32ビットで表現されている3.そして,一つの番地には,8個の0と1が記憶できる.この様子を図 3に示す.

図を見て分かるとおり,2進数の表現は桁数が多くて人間にとって大変である4.そこで,通常は,2進数の4桁をまとめて,16進数で 表す.そうすると,アドレスは16進数8桁,記憶内容は16進数2桁で表すことができ,分か りやすくなる.その様子を図4に示す.

ついでに述べておくが,1個の0あるいは1の情報量を1ビットと言う.8ビットで1バイトと 言う.従って,メインメモリーの一つの番地(アドレス)には,1バイト(8ビット)の情報が 記憶できる.

メモリーについて覚えておくことは,以下の通りである.

-4pt

図 3: メモリーのモデル(2進数)
\includegraphics[keepaspectratio, scale=1.0]{figure/memory_binary.eps}
図 4: メモリーのモデル(16進数)
\includegraphics[keepaspectratio, scale=1.0]{figure/memory_hexadecimal.eps}

ところで,CPUは,どのようにしてメモリーに情報を書き込んだりメモリーから情報を読み込んだり するのだろうか? 簡単にその仕組みを説明するので,図2 のアドレスバスとデータバスを見よ5.CPUは読み書きを行いたいアドレスをアドレスバス の電圧を使って,メモリーに知らせる.32本のアドレスバスの電圧をhigh--1の状態-- とlow--0--の状態にすることにより,32ビットのアドレスを指定する.すると,8本の データバスをとおして,データが流れるのである.読み込み/書き込みの区別は,CPUが制 御線の電圧で決め,それに応じてメモリーが動作する.

2.4 メモリー中の変数の値

2.4.1 変数のバイト数

C言語では,変数の型により,データのサイズが異なる.諸君が使っているパソコンの型 毎のデータのバイト数は表1の通りである.文字型であれば, ひとつのアドレス内に格納することができる.ひとつのアドレスには1バイトのデータが 格納でき,文字型のデータは1バイトの情報を持つからである.整数型では4つ,倍精度実 数型では8個のアドレスが必要である.ひとつのアドレスにひとつのデータが記憶さえれてい る訳ではない.

付録のリスト4にデータ型のバイト数を調べるプログラムを載せておく.

表 1: 変数の型とバイト数
型名 データ型 バイト数 ビット数
文字型 char 1 8
整数型 int 4 32
倍精度実数 double 8 64

2.4.2 メモリー中のビットパターン

それでは,実際にメモリーにデータが格納する様子を見よう.次のようにプログラムに書 いたとする.
  double x=-7.696151733398438e-4;
  int i=55;
  char a='a';

それぞれのデータは, -4pt となっている.実際にこれを確かめるプログラムを,付録のリスト5 に示している.このプログラムを私のパソコンで実行させると,図 5のようなメモリー配置になっていることが分かっ た.表1の通り,整数型と実数型は複数のアドレスにわたって データが格納されていることが分かる.

鋭い学生は,データの並びが逆であることが分かるであろう.例えば,整数のiであ るが, $ (55)_{10}=(00000037)_{16}$なので, $ 00\rightarrow 00\rightarrow
00\rightarrow 37$と並ぶと考えるだろうが,実際は図 5のように逆に並ぶ.これはCPUがそのように作ら れているからである.このように逆に配置させる方法をリトルエンディアンと 言う.Intel社のCPUはリトルエンディアンである.一方,そのままのメモリーに配置する 方法はビッグエンディアンと呼ばれる.ここで述べたように,メモリーにデー タを並べる方法は2通りあって,それをバイトオーダーと言う.どちらがより良いかは分 からない.

ここで,理解しておくべきことは,以下の通りである.

図 5: メモリー中に格納されたデータの例
\includegraphics[keepaspectratio, scale=1.0]{figure/data_in_memory_hexadecimal.eps}

2.5 プログラムが格納される様子

これまでは,メモリーのデータの格納方法を学習した.まえに,プログラム (命令とデータ)は全てメモリーに格納されると述べた.ここでは,もう少し進んで,プロ グラムがメモリーの中にどのように格納されているか調べてみよう.この辺のことと,マ シン語が分かると,ハッカー(クラッカーと言った方が適切かも)になれるかも$ \cdots$

それでは,リスト1に示す簡単なプログラムで,データとメモリー の格納アドレスを調べてみよう.このプログラムの各行の動作は,以下の通りである.まだ,詳 細は分からなくても良いが,大体の流れをつかんで欲しい. -4pt

12行
main関数が格納された先頭アドレスを表示.関数名は,関数のプログ ラムが格納されている先頭アドレスを示している.それは,変換指定子 %pでディスプレイに表示することができる.
13行
関数funcが書かれている先頭アドレスを表示.
14行
変数iの先頭アドレスを表示.変数名に& を付けると,その先頭 アドレスを取り出すことができる.&はアドレス演算子である.
26行
変数iの先頭アドレスを表示.
27行
変数jの先頭アドレスを表示.

   1 #include <stdio.h>
   2 int func(int i, int j);
   3 
   4 /*======================================================*/
   5 /*   メイン関数                                          */
   6 /*======================================================*/
   7 int main(void)
   8 {
   9   int i;
  10 
  11   printf("--- address -----------\n");
  12   printf("\tmain\t%p\n", main);
  13   printf("\tfunc\t%p\n", func);
  14   printf("\tmain-i\t%p\n",&i);
  15 
  16   i=func(5,3);
  17 
  18   return 0;
  19 }
  20 /*======================================================*/
  21 /*  func 関数                                           */
  22 /*======================================================*/
  23 int func(int i, int j)
  24 {
  25 
  26   printf("\tfunc-i\t%p\n",&i);
  27   printf("\tfunc-j\t%p\n",&j);
  28 
  29   return i*j;
  30 }
\fbox{実行結果}
	--- address -----------
	        main    0x8048368
	        func    0x80483eb
	        main-i  0xbffff6b4
	        func-i  0xbffff690
	        func-j  0xbffff694

実行結果から,命令とデータは図6のようになっ ていることが分かるであろう.命令である関数は,大体近くのメモリの先頭付近に配置さ れている.しかし,データの内容を格納する変数は,ずっと離れてメモリーの後ろの方に 割り当てられている.

関数の中で宣言される変数は,ローカル変数と言い,その宣言した関数でのみアクセスが 可能である.従って,同じ名前であるが,違う関数で宣言されたローカル変数は全く別物であ る.図6で分かるように,関数mainと関数 funcで同じ名前のローカル変数 i を宣言してるがメモリー上の配置は全く異 なる.このことからも,名前は同じであるが,全く違うものであることが理解できる.

ここで,理解しておくべきことは,以下の通りである.

-4pt
図 6: プログラムのメモリーへの格納.記憶の内容は不明なので,??としてい る.
\includegraphics[keepaspectratio, scale=1.0]{figure/program_in_memory_hexadecimal.eps}

ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成19年2月9日


no counter