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

●SBB命令の計算方法

SBB命令は、(下位桁からの)ボローがあれば、それも含めて減算を行います。
SUB命令はボロー(実際はキャリーフラグ)があっても、それは無視して、8ビットの数同士の減算のみを行います。
SUB命令は8ビットの数の減算か、あるいは16ビット、24ビットなど8ビット以上の数の、最下位の8ビットの減算に用いられます。
それに対してSBB命令は、下位桁からのボローを含めて減算しますから、8ビットよりも大きい数の計算で、最下位の8ビット以外の部分の減算に使われます。

前回、10進数の減算を、2進数と同じように、「補数」を使って加算することで、同じ結果を得ることができる、という説明をしました。
その計算を1桁ごとに分解してもできるはず、と書きました。
せっかく10進数での計算例を使いましたから、SUB命令とSBB命令の違いを、その計算例で考えてみることにします。

前回は、10進数の減算で、下の計算の例について考えました。

  423
  142(
  281

この計算を、2進数のときと同じように考えて、引く数の142を、「10の補数」というものに変換すると、下の足し算にすることができる、という説明をしました。

  423
  858(
1 281

SUB命令では、「補数」の加算によって、桁上がり(減算なので、じつはボロー)が発生したら、それを無効にし、逆にボローが出なければ、ボロー(キャリーフラグ)をセットします。
上の加算では、上位桁へのキャリーが出ますから、ルールによって、これを無効にすると、結果は普通に減算したときと同じ答えの281になります。

上の計算例では、引く数142をひとまとめにして、「10の補数」を作って、それを423に加算しました。
じつは、2進数の減算の回路では、「2の補数」をつくる代わりに、「1の補数」を加算するときに、つねに下位桁からのキャリーをONにして、一緒に加算してしまうことで、結果的に、「2の補数」を加算するのと同じになる、という回路の説明をしました。
話を合わせるために、上の10進数の補数の計算も、「10の補数」ではなくて、「9の補数」とキャリーを加算する、というように変えて考えることにします。

  423
  857   ……142の「9の補数」
    1(+ ……強制的にキャリーを加算する
1 281
↑計算の結果のキャリーは反転する

ということになります。なお「10の補数」「9の補数」については、前回([第195回])を参照してください。

さてそこで、今度は同じことを、1桁ごとにやってみます。

最下位はもともとの減算では、3−2の計算をしています。
ここを、「9の補数」+キャリーの加算に変換すると、3+7+1=11になります。
ですから、最下位桁の答えは1です。
上位桁への桁上げ(キャリー)が発生しますが、SUB命令のルールでそのときは逆にキャリーを無効にします。
この最下位の計算は、SUB命令の計算です。
ここで加算しているキャリーは、この計算より前のキャリーフラグの状態には関係無く、いつでもキャリーが立っているものとして「強制的」に加算するものです。

さて、それでは、その上の桁の計算をしてみましょう。
次の桁の計算は、もとの減算では、2−4の計算です。
これを「9の補数」+キャリーの加算に置きかえるのですが、今度は上位桁の計算ですから、下位からのボロー(キャリー)を含めて計算する、SBB命令での計算になります。

でも、下の桁からのボローは、さきほど無効にしてしまいましたから、無いわけです。
すると、実質的にはSUB命令と同じことになりますから、さきほどと同じ計算をすればよいはずなのですが…。
とにかく計算をしてみることにしましょう。
4の「9の補数」は5です。
2−4の計算は、2+”4の「9の補数」”+強制的キャリーの加算に置き換えられるはずですから、2+5+1=8になります。

この桁も、結果は一致しました。
ところで。
今回の2+5+1=8の計算では、上位桁へのキャリーは発生しません。
そのときは、SUB命令のルール4)によって(これについては、SBBでも同じルールです)、上位桁へのキャリーを発生させます。
ですから、このさらに上位の桁の計算では、このキャリーを加算することになります。

では、最後の桁の計算です。
もとの減算では、4−1の計算です。
1の「9の補数」は8です。
すると、「9の補数」で置き換えた加算は、4+8(1の「9の補数」)+1(強制的キャリー)+1(下位桁からのキャリー)=14になるはずです。

あれえ。結果が合いませんね。
3桁目の計算結果は2のはずでした。なぜ計算が合わないのでしょう?

うーん。
なぜなのか、実のところ、本当の理由は、私にはわかりません。
多分、数学に強い方ならば、その理由もわかるのではないかと思うのですが。
ただ、どうすればよいのか、ということについては、試行錯誤によってつかむことができました。
それは次のルールです。

SUB命令(SBB命令でも同じ)の4)のルールでは、計算結果の上位桁へのキャリー(ボロー)は、結果を反転させる、というものでした。つまり計算の結果、キャリーが出たら、キャリーをクリアし、逆にキャリーが出なければ、キャリーをセットする、というルールです。
SBB命令の、下位桁からのキャリーを含む計算も、このルールと同じようにするのです。
SUB命令では、「9の補数」の加算のときに、強制的にキャリーを加える計算をしました。
じつは、これは”SBB命令で、下位桁からのキャリーが無い場合”と同じ計算になるはずです。
つまり、SBB命令で、下位桁からのキャリーが無い場合は、(SUB命令でキャリーを無視する場合と同じなので)逆にキャリーを加算します。
1桁目と2桁目の計算がたまたま同じ方法で良かったのは、そういう理由からだったのです。

そして、以上の推察から考えて、SBB命令で、下位桁からのキャリーがある場合には、逆に、キャリーの加算を止めてしまえばよいはずなのです。

このように考えると、先ほどの3桁目の計算は次のようになります。
3桁目の計算は、下位桁からのキャリーがありますから、逆に、「9の補数」にキャリーの加算をするところを、その加算はしないでおくのです
4+8=12になります。
そして、ここで発生した上位桁へのキャリーは、反転させて、クリアします。

以上がSBB命令の回路の考え方なのです。
今回は10進数の計算で考えましたが、2進数でも同じなのです。

本日は時間が無くなってしまいました。
2進数での計算についての説明は、また次回にいたします。
2009.4.3upload

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