コンピュータができることは少ない,
言語を駆使して思い通りに動かそう

講師 矢沢 久雄

 連載2回目のテーマは,プログラミングである。たくさんの言語の紹介と,プログラム・コードを使ってコンピュータを動かす仕組みを解説する。BASICやC言語などの言語は,それぞれ得意分野を持ち,目的に応じた使い分けが可能だ。また,コンピュータができることは,データの入力,演算,出力の3つしかない。コンピュータができることと,コンピュータに正しい命令を与える方法を学べば,プログラミングは難しくない。

 今回は,プログラミング言語と,プログラミング言語を使ってコンピュータに語りかける作法を説明しよう。「プログラミング」とは「プログラム」を作る作業のことだ。プログラムとはコンピュータに与える命令のことであり,その命令を表すために使われる言語体系が,「プログラミング言語」である。

 「言語」という言葉のイメージから,コンピュータに対するプログラマの愛情が感じ取れるだろう。自分の命令どおりにコンピュータが動作した時,プログラマは喜びを感じ,コンピュータを友達のように親しく感じる。コンピュータは,プログラマが記述したプログラムを忠実に実行する機械である。もし,コンピュータが思いもよらない動作をしたとしても,それはプログラムを書いたプログラマの責任でしかない。

 以下では,前半で様々なプログラミング言語を,後半でプログラミング手法の基礎を解説する。サンプル・プログラムには,BASICを使うことをご了承願いたい。

プログラミング言語
マシン語からCOBOL,Visual Basicまでを紹介

図1●マシン語で記述したプログラム例(2進数表記)
0と1だけで記述。OFFの状態とONの状態を示している
 皆さんは,何らかのプログラミング言語に触れたことがあるだろう。もしプログラミングの経験がなくても,BASICやC言語といったプログラミング言語の名前を聞いたことがあるはずだ。まず,プログラミング言語が誕生した歴史的な経緯を説明することにしよう。

コンピュータが理解できるのはマシン語だけ

 まずは,図1[拡大表示]を見てほしい。これは,200を100で割った結果を求める,というプログラムの一部分である。意味不明な0と1の羅列にしか見えないが,実は2進数を使ったプログラムである。0と1の一つひとつが,コンピュータのCPUに与えるプログラム・コード*1を表している。2進数の0と1は,CPUのピンに与える電気信号の0Vと+5Vを表わしている。図1に示したパターンで電気信号を与えれば,CPUの内部で200を100で割るという動作が実行される,というわけだ。このように,電気信号で表されたプログラム言語のことを「マシン語」または「機械語」と呼ぶ。2進数はけた数が多くて取り扱いが難しいので,図2[拡大表示]に示したように,16進数を使ってマシン語を表記するのが一般的である*2

図2●マシン語で記述したプログラム例(16進数表記)
図1と同じ内容を示している
 コンピュータは電気仕掛けであるため,マシン語しか理解できないのは当然である。実際に大昔のプログラマは,マシン語でプログラムを作成し,それを0Vと+5VのON/OFFスイッチを使ってコンピュータに入力していた(図3[拡大表示])。マシン語は,世界初のプログラミング言語とも言える。

ニックネームでプログラミングするアセンブラ

 プログラムに要求される機能が複雑になってくると,マシン語でプログラミングするのは大変な困難を伴う。2進数や16進数は数字の羅列でしかないので,長いプログラムを記述するのは面倒である。そこで,一つひとつのマシン語に,その動作を表す英語のニックネームを付けると言う方法が考案された。このニックネームのことを「ニーモニック」と呼び,ニーモニックを使ったプログラミング言語のことを「アセンブリ言語」と呼んだ。

図3●大昔のプログラミング
ON/OFFのスイッチを使って,コンピュータを動かしていた
 図1や図2に示されたマシン語のプログラムをアセンブリ言語で表すと,図4[拡大表示]のようになる。ニーモニックで表記しているため,図1や図2に比べるとはるかに分かりやすい。アセンブリ言語の特徴は,マシン語と1対1に対応していることである。従って,CPUとアセンブリ言語は,1対1の関係である。ちなみに,図4のアセンブリ言語は,x86シリーズと呼ばれる米Intel製CPUの例である。他の種類のCPUでは動作しない。

 アセンブリ言語で記述したプログラムを実行するには,プログラムをマシン語に変換する必要がある。ニーモニックとマシン語の対応表は,CPUのメーカーが提供した。プログラマは,ニーモニックとマシン語の対応表を片手に,手作業でアセンブリ言語からマシン語への変換を行ってきた。この作業のことを「ハンドアセンブル」と呼んだ。

図4●アセンブリ言語で記述したプログラム例
図1と同じ内容を示している
 そのうち,ハンドアセンブルを自動化する「アセンブラ」というプログラムが開発された。何らかのテキスト・エディタでアセンブリ言語のプログラム・ファイルを作れば,アセンブラがマシン語のプログラム・ファイルに変換してくれる。アセンブラは,アセンブリ言語をマシン語に変換する翻訳者のようなものだ。アセンブリ言語を使ったプログラミングは,ワンチップ・マイコンなどを使った計測制御の分野で,今でも使われることが多い。

様々な高水準言語が登場

 コンピュータが様々な業務で使われるようになるにつれ,要求されるプログラムの数が増え,たくさんのプログラマが必要になってきた。しかし,マシン語で複雑なプログラムが作成できる人は,滅多にいない。アセンブリ言語を使いこなせる人も少ない。そこで,より簡単に習得できるプログラム言語が必要になった。プログラミング言語が簡単に習得できるように,人間の言葉に近いプログラム言語が考案された。それが,BASICやC言語などを代表とする「高水準言語」または「高級言語」と総称しているプログラム言語である。なお,高水準言語に対して,アセンブリ言語のことを「低水準言語」と呼ぶことがある。これは,機能が高い低いという区別ではない。人間の言葉に近いほど高水準である,という意味だ。

図5●高水準言語の違い
同じ処理をさせる場合でも,言語ごとに文法が存在するためプログラムは異なる。図の例は,200を100で割った結果をディスプレイに出力する場合である
 図5[拡大表示]は,FORTRAN,COBOL,BASIC,PASCAL,C,およびC++*3という6種類の高水準言語のプログラミング例だ。いずれも,200を100で割った結果をディスプレイに表示する,という動作を記述している。いずれの言語も,人間の言葉に近いという点では共通しているが,全く同じではない。WRITEやDISPLAYなどのように,表現に微妙な違いがある。これは,プログラミング言語の方言である。それぞれの高水準言語の考案者は,特定分野のプログラムを作成しやすいようにプログラミング言語を設計した。COBOLは事務計算,FORTRANは科学技術計算,といった具合だ。一般的には,表1[拡大表示]に示したような分類が行われる。表1はあくまでも言語の得意分野であって,他の分野のプログラミングに使えない,という訳ではない。例えば,C言語*4はOSの記述を得意としているが,科学技術計算を行うプログラムを記述することも,もちろん可能である。

 様々な高水準言語が登場したことで,コンピュータに語りかける選択肢が増えた。ありがたいことである。というのは,目的に応じて,最適なプログラミング言語を使い分けることができるからである。また,1つのプログラミング言語をマスターすれば,他のプログラミング言語を使うことはそれほど難しくはない。ベテラン・プログラマは自分の得意なプログラミング言語を1つ熟知しているが,それに加えて,目的に応じて他のプログラミング言語を使うことがある。これは,第1外国語として英語を完璧にマスターし,第2外国語としてドイツ語をちょっと使える,というのと同様である。

プログラミング言語の文型はどの言語も同じ

表1●高水準言語の得意分野
 プログラミング言語の種類は異なっても,高水準言語の文法は,どれも英語に似ている。これは,どのプログラム言語も英語圏の人たちが考案したからだ*5。英語の文法には,主語,述語,目的語などを組み合わせた「基本の5文型」があるが,プログラム言語の文型は1つしかない。すべて命令文になっている。これは,プログラミング言語が,コンピュータに命令を与えるための言語であるからだ。英語の命令文は“Give Me Money(我に金を与えよ)”のように「動詞+目的語」という順序になる。同様に,プログラミング言語の構文も必ず動詞で始まり,その後ろに処理の対象となる目的語が来る*6図6[拡大表示])。経験のないプログラミング言語で記述したプログラムであっても,「英語の命令文だ」と思えば,何となく意味を理解できるはずだ。

 ただし,“=(イコール)”による値の代入は,ちょっとだけ例外だ。図5のBASICで記述したプログラムを見てみよう。3行目のPrint sは,いかにも英語の命令文であり,「変数sを印刷せよ」という意味であることが分かる。注目したいのは,その前の2行である。s=200やs=s/100は方程式のようにも見えるが,実際には方程式ではない。ほとんどの高水準言語のイコールは,式の右辺の値を左辺に格納せよ,という命令を表す。この混乱を避けるために,BASICの文法では,式の先頭にLet(~せよ)という命令を置いて,Let s=200やLet s=s/100という記述もできる*7。これなら「sに200を格納せよ」や「sにsを100で割った結果を格納せよ」という意味であることが明確だ。

図6●プログラミング言語の文型は1つだけ
 初めてプログラミング言語に触れた人が,a=a+1というプログラム・コードを見ると,がくぜんとするそうだ。なぜなら,a=a+1を方程式と解釈すれば,「0=1・・・そんなバカな!」と思うからだ。プログラム・コードとして解釈すれば,「aに1を加え,その結果をaに格納する」という意味になる。

様々なCPUで動くプログラムが記述可能

 高水準言語には,人間にとって分かりやすい言語であるという以外に,もう1つ重要な利点がある。それは,異なるCPUを搭載したコンピュータで,同じプログラム・コードが使える点だ。マシン語やアセンブリ言語といった低水準言語で記述したプログラムは,特定のCPUしか理解できないプログラムである。

 それに対して高水準言語は,複数のCPUに対応する。高水準言語の命令とマシン語の命令は1対1に対応しない。複数のマシン語を組み合わせて実現する動作を,1つの高水準言語の命令で表すことができる。例えば,BASICのPrint命令は,複数のマシン語に対応する。高水準言語の命令はマシン語の命令から独立しているため,同じCPUで動くプログラムを記述する高水準言語は,複数存在する。現在では,BASICやC言語など様々な種類の高水準言語が存在し,複数のCPUに対応するマシン語に変換できる。

 なお,アセンブリ語で記述したプログラム・コードをマシン語に変換するプログラムをアセンブラと呼ぶのに対し,高水準言語で記述したプログラム・コードをマシン語に変換するプログラムを「コンパイラ」と呼ぶ。また,アセンブラを使った変換作業のことをアセンブルと呼び,コンパイラを使った変換作業のことをコンパイルと呼ぶ。高水準言語で記述したプログラム・コードの場合,Intel製CPUのマシン語に変換するコンパイラがあれば,Intel製CPUで動作する。同様に,他社のCPUのマシン語に変換するコンパイラがあれば,他社のCPUで動作する。高水準言語は,コンパイラを変えることによって,同じプログラム・コードを異なるCPUのマシン語に変換できる。

 余談になるが,UNIXには,プログラムをネットワーク上から入手する「Ports(ポーツ)」と呼ばれる仕組みがある。Portsは,サーバー上にC言語で記述したソース・ファイルを配置し,それをダウンロードしてコンパイル,実行するというものだ。UNIXは,様々な種類のCPUを搭載したコンピュータで使われている。それぞれのコンピュータには,C言語で記述したソース・ファイルをCPUの種類に応じたマシン語に変換するコンパイラを装備している*8。C言語という高水準言語で記述したソース・ファイルだからこそ,Portsの仕組みが実現できる。

逐次通訳する「インタプリタ」

 高水準言語を使ったプログラム作成は,テキスト・エディタを使ってソース・ファイルを作成し,コンパイラでマシン語のバイナリ・ファイルに変換する。マシン語に変換する前のプログラム・ファイルを「ソース・ファイル」と呼び,マシン語のプログラム・ファイルを「バイナリ・ファイル」や「実行可能ファイル」と呼ぶ。高水準言語の種類ごとに専用のコンパイラが提供されている。BASICで記述したプログラムは,BASIC専用のコンパイラでマシン語に変換する。アセンブラと同様に,コンパイラも翻訳者のようなものだ。

 かつては,コンパイラが単体で提供され,プログラマは自分の好みのテキスト・エディタを使ってソース・ファイルを記述していた。最近では,テキスト・エディタ,コンパイラ,およびデバッガ*9などがセットになった「統合開発環境」が一般的だ。例えば,Visual Basicはプログラミング言語としてBASICを採用した統合開発環境であり,Visual C++はプログラミング言語としてC++を採用した統合開発環境である。

 近年のインターネットの普及とともに登場したプログラミング言語にJava(ジャバ)がある。Javaは,C++に似た構文を採用した高水準言語である。Javaで記述したプログラムは,他の高水準言語と同様にコンパイルする。だがJavaの場合,コンパイルした結果はマシン語にならない。CPUに依存しない「中間コード」を生成する。中間コードは,マシン語に変換しなければ実行できない。マシン語への変換は,プログラム全体を一気に変換するのではなく,逐次変換する方法を採用している。1行変換しては実行し,また次の行を変換しては実行する,ということを繰り返している*10。このような変換方法を行うプログラムのことを「インタプリタ」と呼ぶ*11。アセンブラやコンパイラが一括変換を行う翻訳者なら,インタプリタは逐次変換を行う通訳のようなものだ。インタプリタは,Javaだけの特徴ではない。BASICなどにも,インタプリタ方式の逐次変換を行える統合開発環境を提供するものがある*12