本当に初心者の人に捧げるコンピューター入門


ソフトウェア プログラム編その3

まずは機械語

 前章までででやっとアルゴリズムができました。しかしここではまだアルゴリズムは日本語で書かれています。これでは当然コンピューターは理解できません。
 そこでコンピューターの理解できる言語、すなわちプログラム言語に翻訳してやる必要があります。

プログラム言語に必要なもの



 まずプログラム言語は少なくとも以下のような機能の表現ができないと困ります。

  • メモリーに値を書いたり読んだりする命令
  • 値を計算する命令
  • 値を比較する命令
  • ある条件が正しければA、そうでなければBを行えという命令
  • 「〜または〜」とか「〜かつ〜」とか「〜でない」といった判断
  • ※に戻るとかいう命令
 前章の説明でもこのぐらいはできるという前提で書いていますね。実際にコンピューターも、上記にあるぐらいのことであれば実行する機能を備えています。
 こういう命令を実行するための装置がCPUです。


機械語



 それではCPUが実際に分かる言語から話を始めましょう。CPUが直接理解できる言葉は、そのものずばりの機械語と言われます。
 今まで何度もコンピューターは数字しか分からないと書いてきました。これは機械語にもそのまま当てはまります。すなわち機械語とは見た目はメモリーのある領域に連続して書かれている数字の列なのです。
 前にもちょっと記したとおり、コンピューターはこの数字列を最初から順番に読んでいって、その意味を解釈し、その指示に従った動作を行います。

 それでは機械語にはどんな言葉や文法があるのでしょうか?
 以下の例は、話を少しでも簡単にするために筆者がでっち上げた、現実には存在しない機械語です。
 出てくる命令は必要最低限に押さえ、本当はメモリーには0〜255までの数しか書けませんが、ここでは一つのメモリーに書き込める数の大きさは0〜65535とします。こうでもしておかないと、後で実際のプログラムを作る際に、ただでさえややこしい物がますますややこしくなってしまいます。
(ややこしくてもいいから本物の機械語を知りたいという人はこちら


(1)データ転送命令

 メモリーに値を書いたり読んだりする命令です。

機械語 アセンブリ言語 意味
 10 X Y  LD  X  Y 値YをX番地に書き込め
 11 X Y  LD  X [Y] Y番地の内容をX番地に書き込め
 12 X Y  LD [X] Y 値YをX番地の中身が示す番地に書き込め
 13 X Y  LD [X] [Y] Y番地の内容をX番地の中身が示す番地に書き込め

X,Yというのは適当な数を表します。以下同様です。

  • 12,13で「X番地の中身が示す番地」とかいうややこしい物があります。何でこんな物がいるのでしょうか?その理由は「番地」でデータを管理している以上、この機能がないとプログラムしているときにあらかじめ分かっている番地にしかデータを書けないことになるからです。

(2)演算命令

 値を計算する命令です

機械語 アセンブリ言語 意味
 20 X Y   ADD X  Y X番地の値+Yの結果をX番地に書き込め。
 21 X Y   ADD X [Y] X番地の値+Y番地の値の結果をX番地に書き込め。
 22 X Y   SUB X  Y X番地の値−Yの結果をX番地に書き込め
 23 X Y   SUB X [Y] X番地の値−Y番地の値の結果をX番地に書き込め
 24 X Y   CMP X  Y X番地の値とYを比較する
 25 X Y   CMP X [Y] X番地の値とY番地の値を比較する
 26 X Y   CMP [X] Y X番地の中身が示す番地の値とYを比較する
 27 X Y   CMP [X] [Y] X番地の中身が示す番地の値とY番地の値を比較する

 ここで前にもちょっとだけ書きましたが、コンピューターは一定範囲の整数しか扱えません。そのため計算した結果がその範囲に収まらないことが当然あります。その場合でも強引に計算をして、例えば255+1=0になってしまうと言いました(この偽機械語の例なら、65535を越えたら桁あふれしてしまいます)

 しかし計算結果の0が桁あふれして0になったのか正しい計算の結果0になったのかを判別できないとやっぱり困ります。そこでCPUの内部にはフラグというちょっとしたメモリーがあって、そこに今やった計算の結果に関しての情報が書き込まれます。
 この機械語では以下の3種類のフラグがあるとします。

ゼロフラグ 計算結果がになったときは0以外ではが書き込まれる。比較命令の場合、等しいときは1、等しくないときは0になる。
符号フラグ 計算結果が0か正の値になったときにの値ではが書き込まれる。比較命令の場合、前の項が大きいか等しいときは0、小さいときは1になる。
キャリーフラグ 計算結果が桁あふれしたときしなかったときはが書き込まれる。比較の命令の場合には、何もされない。


(3)ジャンプ命令

 プログラムは通常1000番の命令を読んだら、次は1001番といったように前から順番に実行されますが、その実行の順序を強制的に変更する命令です。前節のアルゴリズムの説明で「6.に戻る」といったような表現がありましたが、これを実現するためにはこのジャンプ命令が必要なのです。

 ジャンプ命令には単純にジャンプする以外に、フラグの状態を見てジャンプする命令もあります。これを利用して、ある条件の場合にはこれ、そうでないときはこれといった条件判断の処理を行うことができるようになります。

機械語 アセンブリ言語 意味
 30 X   JP  X  無条件にX番地の命令に飛べ
 31 X   JP [X]  無条件にX番地の中身が示す番地に飛べ
 32 X   JS  X  符号フラグが1であればX番地の命令に飛べ
=直前の計算結果が正の場合にはX番地に飛べ
 33 X   JZ  X  ゼロフラグが1であればX番地の命令に飛べ
=直前の計算結果が0の場合にはX番地に飛べ
 34 X   JC  X  キャリーフラグが1であればX番地の命令に飛べ
=直前の計算結果が桁あふれした場合にはX番地に飛べ
 35 X   JNS X  符号フラグが0であればX番地の命令に飛べ
=直前の計算結果が0以下の場合にはX番地に飛べ
 36 X   JNZ X  ゼロフラグが0であればX番地の命令に飛べ
=直前の計算結果が0でない場合にはX番地に飛べ
 37 X   JNC X  キャリーフラグが0であればX番地の命令に飛べ
=直前の計算結果が桁あふれしていない場合にはX番地に飛べ


(4)論理演算命令

 条件判断の時にはこれとこれが正しいときはとか、こうじゃないとき、などといった複雑な条件を指定したい場合がよくあります。そういうときにこの論理命令を使います。
 多分昔に下のような表を見たことはありませんか?

 真の否定  → 偽   1の否定  → 0 
 偽の否定  → 真   0の否定  → 1 

 真かつ真  → 真   1かつ1  → 1 
 真かつ偽  → 偽   1かつ0  → 0 
 偽かつ真  → 偽   0かつ1  → 0 
 偽かつ偽  → 偽   0かつ0  → 0 

 真または真 → 真   1または1 → 1 
 真または偽 → 真   1または0 → 1 
 偽または真 → 真   0または1 → 1 
 偽または偽 → 偽   0または0 → 0 

 コンピューターの世界では真を1、偽を0と定義しておいて、正しいとか違っているという概念を右のように表します。

機械語 アセンブリ言語 意味
 40 X     NOT X   X番地の内容を否定した結果をX番地に書き込む
 41 X Y   AND X Y  X番地の内容かつYをX番地に書き込む
 42 X Y   AND X [Y}  X番地の内容かつY番地の内容をX番地に書き込む
 43 X Y   OR  X Y  X番地の内容またはYをX番地に書き込む
 44 X Y   OR  X [Y]  X番地の内容またはY番地の内容をX番地に書き込む

計算した結果が0になった場合はZフラグに1をセットする。


(5)終了命令

機械語 アセンブリ言語 意味
50  HALT プログラムを終了する


とりあえずの例



 それでは例として100番地から以下のような機械語が書かれていたとします。

番地100101102103104105106107108109110111112
命令10102510114510127021101123
番地113114115116...124125126...
命令121033124... 1010030...

これはこんな動作をします。

  1. CPUはまず100番地の値を読みます。
  2. 値は10(メモリー転送命令)なので101番地にデータを書き込む番地、102番地に書き込むデータが書かれていることが分かります。
  3. 101番地と102番地を読みます。
  4. 10番地に102番地の中身(25)を書き込みます。
  5. 103番地の値を読みます。
  6. 同じように11番地に45という値を書き込みます。
  7. 106番地の命令を読みます
  8. 同じように12番地に70という値を書き込みます。
  9. 109番地の命令(これは足し算の命令)を読みます。
  10. 10番地(今は25)と11番地(今は45)の値を足して10番地に書き込みます(結果は70)
  11. 112番地の命令(これは引き算の命令)を読みます。
  12. 12番地の値(70)から10番地の値(70)を引いて12番地に書き込みます。
  13. 115番地の命令(これはゼロフラグが1だったら指定の番地に飛べという命令)を読みます。
  14. 直前の計算の結果を見ると答えは0です。そのためゼロフラグは1になっています。従って普通ならば次は117番地の命令を読むのですが、この場合は117〜123番地を飛ばして124番地の命令を読み込みます
  15. 124番地の値は10なので・・・
とまあこんな調子でコンピューターは計算を行うのです。


アセンブリ言語



 それにしても機械語は言語と言っても、ほとんど見ただけでは理解不能です(世の中にはこれで会話のできる人もいますが)そこでもう少しユーザーフレンドリーにならないかということで考え出されたのがアセンブリ言語というものです。
 機械語では例えば足し算をしろとかいう命令は20という数値ですが、そう書く代わりに"ADD"という記号を使うのです。

 これを使えば前項の機械語の例はこう書けます。左の行番号のようなものは、その命令の始まる番地です。

 100   LD  10  25
 103   LD  11  45
 106   LD  12  70
 109   ADD  10 [11]
 112   SUB  12 [10]
 115   JZ  124
 117   ...
 124   LD  10  30
 少し見やすくなりました。しかしこうしてしまったら人間には読みやすくなりますが、コンピューターには分からなくなります。そこでアセンブリ言語で書かれたプログラムを機械語に翻訳しなければなりません。それはどうするのでしょう?

 それはかつては手でやっていました!機械語との対応表を片手に、アセンブリ言語を手で機械語に直していたのです。
 意味がないって?いえいえ、プログラムを考えるときには機械語で考えるよりもアセンブリ言語を使った方がわかりやすいはずです。アセンブリ言語のレベルでプログラムができてしまえば、それを機械語に直すのは単純な作業です。こうすることで機械語で物を考えるよりは間違いはずっと減るのです。

 でもそうは言っても、まだまだこれは間違いやすくうっとうしい作業です。
 そこでこれを自動的に翻訳してくれるプログラムが開発されました。文字列を対応表に従って置き換えるだけなので比較的簡単に作れそうだと想像はつくでしょう?
 これがアセンブラと呼ばれるプログラムです。

他の命令は?



 ところで、前の例はいくら偽機械語だからといっても、あまりにも命令の数が少なすぎるとは思いませんか?メモリーの読み書きはともかく、計算が足し算引き算しかできないなんて、あまりにも情けなさすぎるとは思いませんか?

 ところが実はこれだけで基本の大部分はカバーしてしまっているのです!嘘だと思うのならば、
こちらの本当の機械語の説明を見てみてください。

 で、何が言いたいかというと、ワープロやゲームのような立派なソフトウェアであっても、その中身はほとんどこのような情けない命令の組み合わせであるということなのです。


それでは迷宮からの脱出を・・・



 では次の章では迷宮脱出のアルゴリズムを上のアセンブリ言語で書いてみましょう。
 多分どういうことになるかはもう想像できているでしょうが・・・



前へ 目次へ 次へ