プログラムとは何か?
プログラムとは何か?
一言で答えるなら、それは「コンピューターへの指示書」です。
プログラムは、英語では program という単語で、その語源は pro(前) + gram(書) 。コンピューターへの指示を前もって書いたものが program なのです。
でも、その答えでは「コンピューターとは何か?」がわかっていないと実際とは全然違ったイメージになるかもしれません。




コンピューターとは何か?
コンピューターは計算機
では、コンピューターとは何かというと、つまるところ「計算機」になります。

計算機と言うと、電卓のイメージで、すごくショボい感じがしてしまうかもしれませんが、あれこそがコンピューターの本来の姿なのです。
実際、コンピューターは、英語では、“computer” という単語です。これは、compute(計算する)という単語と、○○するヤツ(人や物)を表す -er がくっついた単語で、計算するヤツ = 計算機 という意味なのです。
ちなみに、電卓は英語で “calculator” と言って、 “computer” と区別されます。
calculate も「計算する」と訳されますが、 calculate は「数字を使って見積もる」というニュアンスなのに対し、compute は「1つの結論(値)を出す」というニュアンスです。数は手段か目的かという違いです。
しかし、私たちの知っているコンピューターは、電卓のような計算機と違って、数字以外の文字を扱えたり、写真や音声、動画も使えたり、ゲームができたりもします。そしてそれらは、電卓でするような、足し算や引き算などの計算とはかけ離れたことのように思えます。
様々なデータを数値化して計算
実はコンピューターの内部で、これらの画面表示や音の再生は、全て数値に置き換えられたデータの集まりになっているのです。
そして、文字を変換したり、写真を加工したり、音楽や動画を再生したり、ゲームでキャラクターを操作したり、という私たちがよく経験するコンピューターの動作は全て、数値の変化によるものです。
元となる文字や画像や音声などから置き換えられた数値(入力データ)を、目的ごとのプログラムで指定された計算によって、別の数値(出力データ)に置き換える処理が、コンピューターの中でものすごい速さで繰り返された結果なのです。
コンピューターは単純計算を超高速で繰り返す
そのプログラムで指定された、複雑にみえる計算も、分解すれば、多数の足し算や引き算などの単純な計算の繰り返しに過ぎないのです。
コンピューターがすごいのは、電卓と同じような計算を、1つの計算あたり約0.000000001秒という超高速で、 プログラムで指定された順番どおりに、 連続してできるところなのです。(つまり、1秒間あたり約10億通りの計算をこなせるということです。)
コンピューター誕生の時代(19世紀~20世紀前半)
計算の繰り返しがめんどい
元々、コンピューターが作られたのは、足し算や引き算といった数値の計算や、暗号の読み書き(文章変換)のような、数ステップでできる単純作業を、とにかくたくさん繰り返したい時に、人力でやるんじゃなくて機械で自動的にできるようにしたい、という動機からでした。
1個や2個なら人力作業でもいいけれど、100個のデータに対して、同じような作業を100個分、繰り返すのなら、人間より機械にやらせた方がいいよね? という発想です。
単純な計算
例えば、最も単純な計算の代名詞は何か?と聞かれれば、多くの人が、この足し算を思い浮かべるかと思います。
1 + 1 = 2
でも、これよりももっと単純な計算だってありますよね?
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
これら3つと先の1つを含めた全4パターンの単純計算だけでも、もし「これらをランダムに100回繰り返し解きなさい」と言われたら、相当大変です。
0 の重要性
0 を含めたこれらの計算は、数学が苦手な人ほど「こんな簡単な計算は、計算のうちに入んないよ」と思うかもしれません。でも逆に、数学を深く理解している人ほど、その重要性を理解しています。例えば、小さい数字から順に4つの式を並べてみましょう。
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 2
こうやって並べて見ると、この 4 行の中に、0 は 5 回、1 は 6 回、出てきました。2 は最後の最後にやっと 1 回、出てきました。0 は、“最も小さい数字”という特殊性を持つだけでなく、“足しても数字を大きくしない”、“足した結果は足す前と同じ”など、0 にしかない様々な特殊性を持った、無視できない数字なのです。
その 0 が持つ、もう一つの重要な特殊性が、“桁を増やして、すべての数を表せる”ということです。
2以降の数字ができるまで
1, 2, …
ここで、ちょっと空想してみてください。数字や数学を知らない大昔の人が、あなたの前で今、まさに「どんどん大きな数の計算をできるようにしよう」としているとします。

大昔の人: 「よし! まず、一個を表す数字を “1” としよう!」
大昔の人: 「次に、もう一個増えたら、それを“2” として表そうかな…」
そして、“2”という数字を初めて作り出して、手を止めました。
大昔の人:「!」
大昔の人:「そうか!どんどん大きな数を考えていくためには、どんどん新たな数字を作り続けなければならないのか…」
桁ができるまで
大昔の人は「大きな数を表すためには、その数の分だけ新たに数字が必要になるのではないか?」と不安になっています。例えば、百を表すためには、それまでに百種類の数字を作らなければならないと。
でも、現代に生きるあなたは「数字は 0 ~ 9 の十個だけあれば良くて、それ以降は、10 の位、100 の位、…と桁を増やしていくだけで大丈夫!」ということがわかっています。例えば、百を表すためには 1 と 0 の 2 種類の数字だけで、100 と表せます。それを大昔の人に教えてあげましょう。
あなた:「数字は 0 ~ 9 だけあればいいんだよ。9 の次は 10、10 の次は 11、…、99 の次は 100 、…って桁を増やせば、大きな数も、9 までの十種類の数字だけで表せるんだから。」
大昔の人:「なるほど、数字は十個でいいんだね。でも、その考えでいったら、桁さえ増やしていけば、もっと数字は少なくてもいいんじゃない? 例えば 0 と 1 の二つの数字だけでも、1 + 1 = 10 (二), 10 (二) + 10 (二) = 100 (四) みたいに、1 より大きな数字は桁を増やして表せるんだから。」
あなた:「うーん、でも数字の数が少ないとそれだけどんどん桁を増やさないといけなくなるし、やっぱり手の指の数と同じ十個がちょうどいいんだと思うよ。」
こうして人類は、0 ~ 9 の数字を使ってどんな数でも表せるようになりました。実際には、あなたは大昔にはいませんでしたが、大昔の人がずっと考え続けて、結局そうなりました。
再びコンピューター誕生の時代へ
指十本で一桁のコンピューター?
それから時代は、先ほどの単純作業の100回繰り返しを自動化する方法を考える時代に変わります。

自動化を考える人:「単純な足し算でも、機械にやらせるのは難しいな。10本の指まで区別させることはできても、さらに桁を増やしていこうとすると、どうしても複雑になる。」

(しばらくして…)

自動化を考える人:「ふー、9 の次に桁を増やすこと自体はなんとかできた。でも、10本も指があるとやっぱり機械が複雑になるな。待てよ、なんで指10本必要なんだ? 機械は人間じゃないんだから、指1本でもいいんじゃないか? 桁を増やすこともできるようになったし。」
指一本で一桁(二進数)のコンピューター

(十進数の “370” に相当)
こうしてできたのが指一本で一桁を表す(指が下向きなら 0、上向きなら 1)、計算機です。
十本の指は数字じゃなくて桁を表すようになったので、十本指なら十桁ですが、十にこだわる必要はなく、この方式で何本でも(何桁でも)計算できるようになりました。
このように、0 と 1 の二個の数字だけで数を表す方式を“二進数”と言います。
それに対して、普段私たちが使っている 0 ~ 9 の十個の数字だけで数を表す方式を“十進数”と言います。
コンピューターは二進数の計算機
電気の OFF / ON
0 と 1 の二つの数字は、指の下向き/上向き でも表せます。2種類の区別ができるものなら何でもいいので、電気の OFF と ON でも表せます。この宇宙で一番速いものは光や電磁波などの電気変動なので、早く計算結果が出せるよう、電気の OFF と ON で数字の 0 と 1 を扱える計算機が作られるようになりました。

スイッチのリレー=電気回路
電気を使って自動計算をするには、電気回路 を使います。電気回路とは、電気の通る道を電気で切り替えるスイッチの集まりです。電気の通る道を電気で切り替えるスイッチを多数つなぐと、リレー競技のバトン渡しのように、スイッチ間で次々と切替動作を引き継げます。このようなスイッチをリレースイッチと言います。


(実際の時間差はごく短く、一斉同時に見える)
電気回路を利用すると、[何桁かの数値]を別の[何桁かの数値]に自動変換することができます。これが電気計算回路です。
計算回路(ワイヤードロジック)
そして電気計算回路は、その回路をどう設計するかで、違う計算処理をすることができます。つまり、回路の設計こそが、世界最初のプログラムだったのです。(ワイヤードロジック[ wired logic : 結線論理 ]と言います)

赤線は+、白線は-
※ 黒線には、実際は抵抗があり、電流が流れると電圧降下する。
電気回路(リレー) ⇒ 電子回路(トランジスタ)
スイッチの集まりである電気回路は、装置サイズが大きく、消費電力も大きなものでした。そのため、計算回路は、半導体でできた電子スイッチ(トランジスタ)による小型で省電力の電子回路に取って替えられました。
論理回路(計算回路の素となる電子回路)
そうすると、より複雑な回路も小さな電子基板で組めるようになりましたが、計算式を変えるたびに、人手で回路を組み替えるのもナンセンスです。そこで、あらかじめ、いくつかの計算回路の素になる共通の回路(論理回路)を、基板に適当に配置・配線しておき、さらに電子スイッチによる電子制御で論理回路の組み替え(論理回路間の配線切替)もやってしまおう、という発想になりました。

上の半加算器にもこのNAND回路が5つ組み込まれています。
このように論理回路を組み合わせることで、様々な計算回路が作れます。
集積回路(IC)
このように複数の論理回路を基板にあらかじめ配置しておき、電子制御でその組み替えをできるようにした回路を集積回路(IC: Integrated Circuit)と言います。1つの論理回路には、数個~数百個のトランジスタが使われ、最近の集積回路には、何万個もの論理回路が組み込まれたものもあります。

電子制御のために、複数のON / OFF 入力スイッチを集積回路につけ、そこへ入力する ON / OFF パターンをマシンコード(機械語)と言うようになりました。これが第二のプログラムです。
同期回路
さらに、複数の計算を連続的にさせるためには、複数のON / OFFパターンが必要です。
そこで、連続的に複数のON / OFFパターンを読み込めるように、クロックから連続的に発信される ON / OFF 信号に同期して、順次 ON / OFFパターンを読み込む集積回路も作られました。これを同期回路と言います。クロックは、水晶に電気を通して得られる一定周期の振動現象を利用した、発信装置です。

クロック同期で論理回路組み替え
同期回路によって、より複雑なプログラムが作れるようになりました。ここからようやく今風のプログラムが始まったと言っても良いでしょう。
同期回路では、論理回路を組み替えるための ON / OFF パターン と、計算対象のデータとしての ON / OFF パターン を、クロックに同期して順次、集積回路に入れられます。
なお、論理回路を組み替えるための ON / OFF パターン をオペコード(opcode)と言い、計算対象のデータとしての ON / OFF パターン をオペランド(operand)と言います。
同期回路は、オペコードとオペランドを、クロックに同期して順次取り込む集積回路とも言い換えられます。
メモリ
メモリは極小充電池
このため、あらかじめ複数の ON / OFF パターンを、「同期回路が読み込める場所」に用意しておけば、あとはクロック任せで複数の計算結果を順次得ることができるようになります。
このように「あらかじめ 複数の ON / OFF パターン を用意しておけて、かつ同期回路が読み込める場所」のことを メモリ (memory)と言います。

メモリの実体も半導体の装置ですが、例えるなら、メモリは極小の充電池の集まりです。極小充電池と同期回路がつながると、極小充電池から同期回路へ放電されます。 各極小充電池へ、放電減少分のほんの少しの電流を補充し続けること(リフレッシュ)で、 複数の ON / OFF パターン をそのまま残しておけます。
さらに、同期回路から出た計算結果( ON / OFF パターン )をまたメモリに入れること(強制充電/強制放電)もできます。これによって、計算結果をまた別の計算に使い回すような、より複雑なプログラムを自動処理させることができるようにもなるのです。
メモリアドレス
ただし、多くのデータ( ON / OFF パターン )を同一のメモリに順次入れていくと、どの部分が何を意味するデータだったのか、先頭から順次解読しない限りわからなくなります。
そこで、分厚い本の各ページにページ番号があるように、メモリの標準的な使用単位ごとに先頭からの通し番号 メモリアドレス(memory address)が付けられるようになりました。
通常は、1 データ分の ON / OFF パターン と同じだけの ON / OFF の個数が、メモリの極小充電池の使用単位になります。上図の例では、8個の ON / OFF で1データ分の ON / OFF パターン になっているので、メモリアドレスとして8個の極小充電池ごとに 0 から 1 ずつ増えていく番地が付けられます。

これにより、先頭から順次解読していかなくても、メモリアドレスを指定して目的のデータを読み書きするような、複雑なプログラムも可能になりました。
ビットとバイト
このようにコンピューターのしくみの中でよく使われる単位として、 ON / OFF の個数に対して、ビット(bit)という単位が付けられ、1 個の ON / OFF パターン で初期の頃に一般的であった 8 ビットに対して、1 バイト(byte)という単位が付けられました。

さらに8ビットの倍の16ビット(2バイト)に対して、1 WORD(ワード)、
さらにその倍の32ビット(4バイト = 2 WORD)に対して、1 DWORD(ダブルワード)、
さらにその倍の64ビット(8バイト = 4 WORD = 2 DWORD)に対して、1 QWORD(クワッドワード)と言うこともあります。
レジスタ
また、計算の都度、集積回路とメモリでやり取りしていると時間もかかるため、集積回路の中にも、 ON / OFF パターン を保持できる、より高速なメモリが入れられました。この集積回路内の高速メモリを レジスタ (register)と言います。
集積回路内に、複数のレジスタを用意しておき、その一部にメモリアドレスを保持させておくことをアドレス参照と言います。
例えば、アドレス参照のためのレジスタには、以下のような専用レジスタがあります。
- プログラムカウンタ[PC]
- 次クロックでプロセッサ入力されるオペコードのメモリアドレスを保持するレジスタ。
- スタックポインタ[SP]
- メモリ上のコールスタック領域のトップアドレスを保持するレジスタ。
- ベースポインタ[BP]
- 現在処理中のスタックフレームのベースアドレスを保持するレジスタ。
トップアドレス、スタックフレーム、ベースアドレスは、コールスタックの用語です。コールスタックについては、こちらを参照してください。
プロセッサ
このように、かつては論理回路でデータ(ON / OFF パターン)の簡単な変換だけをしていた集積回路が、集積回路内にレジスタを持ち、あとで使うメモリのアドレスを保持して、分岐や反復を含む一連の複雑な工程(process: プロセス)をも処理可能になったため、このような高機能の集積回路をプロセッサ(processor)と呼ぶようになりました。
また、高機能なプロセッサの中には、ワイヤードロジックだけでなく、複雑な処理をプログラミングしたマシンコードプログラムが、プロセッサ内部にあらかじめ記録されていて、外部からはそれを一つのオペコードで呼び出せるようにしているものもあります。(マイクロプログラム方式)
さらに、1つのコンピューターに二種類以上のプロセッサを入れ、計算処理などの複雑な工程と、入出力制御などの単純な工程で使い分ける構成も出てきました。この場合、複雑な工程を担当する高機能かつ高性能のプロセッサをCPU(Central Processing Unit)と言い、単純な工程を担当する低性能のプロセッサをコントローラー(controller)とも言います。
ここまでのまとめ
コンピューターの本質は、リレースイッチの組み合わせで、2進数(ON/OFFパターン)を変化させるだけの機械です。(計算機)
そのリレースイッチをどう組み合わせるかによって、2進数をどう変化させるかが決められるので、そのリレースイッチの組み合わせをプログラムと言うようになりました。(初代プログラム)
そのリレースイッチの組み合わせも、別に入力した2進数データによって、瞬時に切り替えられるようにしたのが、マシンコード(オペコード)です。(2代目プログラム)
この後、さらにアセンブリ言語(3代目プログラム)、高級プログラミング言語(4代目プログラム)と続いていくのですが、詳しくは次の記事で説明していきます。