標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第17回]

●DAAのお話の続き(その5 今度こそ、本当に終わり、です)

今までの流れで、こういう見出しになってしまいましたが、DAAについてはもう終わってしまいました。
ほんとうは、2進数の負数のお話の続きです。

前回の答えです。
十進数の加減算は、もとの数が負数のときには、それに正数を加算、減算すると、結果の増減は絶対値で見ると、もとの数が正数のときの加算、減算での結果の逆になります。
100+10=110のようにもとの数が正数のときには結果の数は大きくなりますが、−100+10=−90のようにもとの数が負数のときには、結果の数(の絶対値)は小さくなります。

これに対して、2進数における加減算では、もとの数が正数であっても、負数であっても、結果の値を、符号無し2進数として見てみると、その増減は一致しています。つまり正数を加算した場合にはもとの数が負数でも正数でも結果の値は大きくなり、正数を減算した場合には、小さくなります。

前回の2進数の計算例をもう一度示します。

100+10=110の計算を2進数(16進数)で行います。
 0110 0100    100(16進数の64)
 0000 1010(+   10(16進数の0A)
 0110 1110    110(16進数の6E)

16進数で見ると、もとの数64が6Eになって、値が大きくなります。

−100+10=−90の計算を2進数(16進数)で行います。
 1001 1100    −100(16進数の9C)
 0000 1010(+    10(16進数の0A)
 1010 0110     −90(16進数のA6)

16進数で見ると、もとの数9CがA6になって、こちらも大きくなっています(この説明のように、符号無し2進数の代わりに、16進数で考えた方がわかりやすいと思います)。
それでは、逆に負数を加算したら、どうなるでしょうか?そこまで考えてみることで、10進数の計算と2進数の計算の違いを完全に理解できるのです(と思います)。その検討については、もう少しあとですることにします。

●人間の計算方法(十進数)とコンピュータの計算法(2進数)は根本的に異なっている

十進数の計算は、人間が行いますから、符号付の数の計算を行う場合に、必要に応じて加算なのに引いてみたり、減算なのに足してみたりしながら計算を行っています。
その計算方法は結構大変なのですが、私たちは、もう慣れてしまっているので、普段なんとも思わずにやってしまっているのです。
しかし、これをそのまま、コンピュータにやらせようとすると、これはもう、大変なことになってしまいます。

コンピュータは、非常に頭が悪いのです。まったくどうしようもないほど、バカなのです。
人間の複雑な思考にはとてもついてはいけません。
なんたって、1と0しか理解できないのですから。

どこが、複雑なんだ?
あんたの言ってることは、よくわからないよ!いったい何が言いたいのっ!

すみません。どうも、表現力に欠けるものですから…。
では、簡単な例で説明いたしましょう。

十進数の25+3=28の計算を筆算でやってみましょう。
簡単です。
 25
  3(+
 28
になります。

では、今度は−25+3=−22の計算を同じように筆算でやってみましょう。
 -25
   3(+
 -22
になります。

今度は負数を加算してみましょうか。25+(−3)=22の計算を筆算でしてみましょう。
 25
 -3(+
 22
です。

今度は−25+(−3)=−28の計算を筆算でやってみましょう。
 -25
  -3(+
 -28
になります。

こんな簡単な計算のどこが複雑なのぉ?コンピュータならこの何百倍もすごい計算を瞬時にやってのけるって言うじゃない!

いやぁ、こういう「むつかしい計算」は、コンピュータは大の苦手なんですよ。

ぶつよ、ほんとに!

では、お尋ねしますけれど、上の計算例で、25+3のときには、5に3を足しましたね?

足したよ。

でも、−25+3のときには、5から3を引いてしまいました。

そんなの、当たり前じゃないか!負数の計算では、そうするのっ!学校でならったでしょ!

でも、でも、そのあとの、25+(−3)のときは、5から3を引いているかと思ったら、−25+(−3)のときはまた5に3を足してます。わけがわかりません…。

あのねー。だから、負数の計算はそういうものなのっ!

では、では、お尋ねしますが、もしも、上の計算例で、全体が見えなくて、一番下の一桁しか見えなかったとしたら、どうします?
□□5
□□3(+
のような計算だったら、5に3を足すのですか?それとも5から3を引くのですか?さあ、虫食い算ですよぉ。

できるわけないじゃないのっ!こんなの!インチキ虫食い算だよっ!

推理ドラマなどのナレータのセリフを借りて書いてみますと、
「賢明な読者諸君でしたら、もうお分かりだと思います」

●コンピュータは単純な作業が得意。複雑な思考は、できません。

前回、どこかに書いたと思います。
8ビットのCPUは一度に1バイト(8ビット)の計算しかできません。
16進数わずか2桁しか1度に計算できないのです。
いや、それではまだ的確な表現ではありません。
もっと正確にいうと、8ビットのCPUは一度に1バイト(8ビット、16進数2桁)の数値しか、認識できないのです。

さきほどの十進数の計算例に戻ります。
私たちがこのような計算をする場合には、瞬時にして、符号の有り無しや数の大小をまず読みとって、それから必要な計算方法を選択して、計算を始めます。
しかし、コンピュータは、私たちが日常生活でごく普通にこなしている、この、「瞬時にして全体をとらえる」ということが、苦手中の苦手なのです。

では、コンピュータは、何が一番得意なのでしょうか?
0+0=0、0+1=1、1+0=1、1+1=1+carry、だけの組み合わせしかない演算の繰り返しが、一番得意なのです。
判断は普通減算を利用しますが、その減算すら、前々回の減算に対する十進補正のところでお話しましたように、加算に変換して行ってしまうのです。

いずれ説明するかもしれませんが、「TTLでCPUをつくる組立キット」の回路では、74HC283というICを使います。4ビットの加算器です。このICはその名の通り、加算を行うものです。
8080には加算命令ADDの外に減算命令SUBがあります。
しかし、「TTLでCPUをつくる組立キット」の回路には加算器はあっても、「減算器」はありません。
どうやって加算器だけで減算をおこなうのかというと、まさにその、減算を加算にしてしまう仕組みを、TTL回路でも応用しているのです。

●符号付2進数の特徴とは?

またお話がだんだんとそれていってしまいます。
2進数の負数のお話に戻ります。
8ビットのコンピュータ(CPU)は一度に8ビットしか認識できません。
すると、計算をする場合でも、数値の下位1桁か2桁しか認識できないので、十進数の計算のように、まず負号の有無を確認して、それが有ったら、加算する代わりに減算して、それから、えーと、それから…、というようなことをしていると、回路もプログラムもどんどん複雑になってしまって、わけがわからなくなってしまいます。

符号付2進数の仕組みは、このようなコンピュータの長所と短所を的確にとらえて考え出された仕組みなのです(と、私は思います)。
もう一度前回の答えのお話に戻ります。
符号付2進数に対する計算は、じつはその数を符号無し2進数だと考えて計算してもよい、という構造になっているのです。
これは非常に重要なことなのです。

符号付2進数は最上位ビットが符号ビットになっている、ということはすでに説明しました。
しかし、それは、符号ビット以外のビットだけを見たときには、その数の正負はまったく判断できない、ということも意味しているのです。

だから、一度に1桁か2桁しか認識することも計算することもできない8ビットのコンピュータ(CPU)で、計算をさせるためには、その下位桁や途中の桁だけを取り出したら、足してよいのやら引いてよいのやら判断できない、というような数の仕組みでは使い物にならないのです。
ここでは、8080のお話なので8ビットCPUとして説明しましたが、32ビットや64ビットのCPUでも理屈は同じです。

2進数では、負数のはずなのに、正数だと思って計算しても正しい結果になってしまったり、同じ値の8ビットの数なのに、同時に互いに異なった大きさの正負の2値になってしまったり、というように、ちょっと考えると理屈にあわないと思えるところがありますが、それは実は、正負や数の大小を考慮せずに、その数の一部分だけを取り出して計算することを可能にする、という非常に巧妙な仕組みの上になりたっているのです。

●2進数は「金太郎飴」と同じ

論より証拠!です。せっかく十進数の簡単な加算例をあげて説明しましたから、同じことを2進数でやって、それが本当なのかどうかを確かめてみましょう。

まず、最初は25+3=28です。2進数ではこうなります。
 0001 1001    25(16進数の19)
 0000 0011(+   3(16進数の03)
 0001 1100    28(16進数の1C)

次は、−25+3=−22です。
 1110 0111   −25(16進数のE7)
 0000 0011(+   3(16進数の03)
 1110 1010   −22(16進数のEA)

今度は、25+(−3)=22です。
 0001 1001    25(16進数の19)
 1111 1101(+  −3(16進数のFD)
 0001 0110    22(16進数の16)

最後に、−25+(−3)=−28です。
 1110 0111    −25(16進数のE7)
 1111 1101(+   −3(16進数のFD)
 1110 0100    −28(16進数のE4)

いかがでしょうか?2進数の加算では、足す数や足される数が正数であっても負数であっても、その一部分を取り出して、どのビットの計算に注目してみても、0+0=0、0+1=1、1+0=1、1+1=0+carry、以外のルールは全く使われていない、ということが理解いただけたでしょうか?
ここで例にあげた2進数は、符号付の2進数なのですが、一見不思議なことに、単なる符号を意味するビットのはずの最上位ビットが計算の過程では数値の一部として、桁上げやビット毎の計算に巻き込まれてしまっていることです。つまり2進数では、符号ビットはただの符号の情報を保持しているだけではなくて、同時に数の一部としても機能しているのです。

ずっと昔、少年のころに読んだ手塚治虫の「鉄腕アトム」にムカデの化け物のようなロボットが出てきたことを思い出しました。
顔の無い手と足だけの同じ形をしたロボットが数珠のように合体すると、巨大なムカデロボットになってしまいます。
2進数は、部分だけを見ると全く同じ性質をしていて、くっつけたり、切り離したり、長さをどのようにでも変えられる変幻自在な数なのかもしれません。

(ここではこれ以上は例をあげて説明しませんが)上の計算例では8ビット(16進数2桁)の数値として加算を行いましたが、この計算が、たとえば32ビット(16進数8桁)の2進数の計算の一部としてもそのまま成立しますし、さらには、たとえば100ビットとか1000ビットとかといった巨大な数の計算の一部としても成立してしまう!のです。

前回、DAAの回路図について、2入力のゲートを多用している、ことについてお話をしました。
その理由としては、ここで説明したのと同じ、「コンピュータの考え方の原則」といったようなものを肌で感じる、という目的もあるのです。
CPUのように複雑な働きをする回路でも、2進数の計算と同じように、じつはANDやORの組み合わせのみでつくることができる、ということを実証してみよう、というのが「TTLだけでCPUをつくる組立キット」の大きな目的でもあるのですから。
2008.7.24upload

前へ
次へ
ホームページトップへ戻る