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

●DAAのお話の続き(その3 「減算後の補正について」の続き)

先回、減算における十進補正について、1桁に注目したとき、補正前の数が6〜Fでかつ下位桁からのキャリーフラグが立っている場合に、十進補正が必要である。
というところまで、説明をしました。
本日はその続きです。

●その前に前回の加筆訂正についてのご報告です。

前回は時間が無くて、やっつけで書いてしまいましたので、本日、大幅に加筆訂正をいたしました。
また前々回(加算に対するDAAのお話)で、表およびそれに対する説明に一部不足がありましたので、これも加筆訂正いたしました。

それでは、前回の続きです。
前回の表をよく見て、補正前の数をどのようにすると、期待通りの十進数(BCD数)にすることができるのでしょうか?
うーん。いちいち前のページに戻るのは面倒です。
特別に、先回と同じ表を再掲することにします。

引かれる数
引く数
A
A
A
A
9&borrow→ A
10進数

加算のときは、補正前の数に6を加算すれば、正しく補正が行われました。
減算の場合には?
補正前の数(→の行の数)を補正後の数(その下の行の数)にするには、加算の場合とは逆に6を引けばよいことがわかります。

●減算の代わりに加算する

加算後の十進補正は6を加算するという作業でした。
減算後の十進補正はそれとは逆に6を減算する作業になりそうですが、これは少し面白くありません。
十進数の計算でも加算よりも減算の方がなんとなく面倒な気がします。
2進数の場合でも同じで、できれば減算はやりたくありません。
なんとか減算をやらないで済ますことはできないものでしょうか。

そこで、先回長々とお話した2進数の負数を思い出して欲しいのです。

6を引く代わりに、−6を加算するっていうのは、どうなのだろうか?

−6は、00000110の「2の補数」ですから、11111010(16進数では、FA)です。
00000110を引く代わりに、11111010を足すということでも良い、のでしょうか?
計算で確認してみましょう。

例として、17−9=8について考えてみます。
上の計算をBCD数ではなくて2進数(16進数)であるとして2進数の減算を行うと、その結果は表から、0Eになることがわかります。この0Eから6を引いて、8を求める代わりに、−6を加算することでも、正しく8が求められるかどうかを計算によって試してみます。

0000 1110
1111 1010(+
0000 1000

この方法でも8が求まることが確認できました。
しかしこの場合に、上位桁に対して発生するキャリー(ビット7からのキャリー)は問題があります。
本来は下位桁に対してのみ行ったはずの補正計算の結果、上位桁のそのまた上位桁に波及するキャリーが発生するのは困ります。
そこで、もし上位桁が補正を必要としない数であった場合には、補正計算の結果発生するキャリーフラグはクリアする必要があります。

●上位桁についても同じ考え方ができるか?

8ビットの数はBCD数では2桁の数になります(16進数でも同じ)。
今その下位桁についての十進補正についてはその方法が確認できました。
上位桁に対してはどうなのでしょうか?
上位桁については、減算に対する十進補正では、2桁のBCD数の例では少し都合が悪くなります。
なぜなら、十進補正が必要な場合は、その桁の引かれる数が引く数よりも小さい、という条件と、計算前も計算後も、正の数でなければならない、という2つの条件をクリアする必要があるからです。
そこで、3桁のBCD数を考えて、170−90=80という計算について考えてみることにします。この場合も2進減算の結果は、E0になりますから、このE0から60を引いて80という答えを求めれば、減算後の十進補正が正しく行われたことになります。
そのE0−60の計算を、E0+(−60)という「加算」でも行えるかどうかを確かめてみることにします。

01100000(16進数の60)の「2の補数」は10100000(16進数のA0)です。これが−60(注意。十進数の−60のことではありません)です。

1110 0000
1010 0000(+
1000 0000

この場合にも、正しく結果の80が求まりました。この場合でも、補正計算の過程で上位桁にキャリーが出ます。
しかし、さきほどの下位桁の場合とは異なり、もともと上位桁(上位バイト)に対するキャリー(上位桁からのボロー)が発生していることが、十進補正を行う上での必要条件だったわけですから、このキャリーはそのままにしておく必要があります。

●上位桁と下位桁の両方ともに補正が必要な場合はどうなるか?

最初に下位桁のみに対する補正について検討し、その次に、上位桁のみに対する補正について、検討を行いました。
それでは、上位桁と下位桁の両方が補正を必要とする場合には、どのような計算をすればよいのでしょうか?
加算に対する補正では、下位桁の補正が上位桁に影響を及ぼす場合がありました。
幸い、減算に対する補正は上の2例の計算によって、上位桁が補正を必要としない場合の下位桁に対する補正が上位バイトに対する余計なキャリーを立ててしまうこと以外に上位桁に影響を及ぼすことはなさそうなので、ここは素直に、下位桁のみの補正と上位桁のみの補正をただ単に両方同時に行えばよいらしい、という予想が成り立ちます。
下位桁に対する補正は、補正前の数に−6を加算する、というものでした。
上位桁に対する補正は、補正前の数に−60(16進数の)を加算する、というものでした。
すると、上位桁も下位桁も補正が必要な場合には、16進数の−66を加算すればよいことになります。
16進数の−66は、01100110の「2の補数」ですから、10011010(9A)になります。
つまり補正前の数に9Aを加算すればよいということになります。
これも計算で確かめてみましょう。

175−96=79という計算の例で確かめてみます。この計算がBCD数ではなくて2進数であったとして2進数の減算が行われた結果は、DFという値になります。このDFに9Aを加算して、期待どおりに79という答えが得られるかどうかの検証です。

1101 1111
1001 1010(+
0111 1001

正しく79が求まりました。補正計算の結果、ビット7から上位桁(上位バイト)に対してキャリーが発生しますが、もともと上位バイトに対してはボローが必要なので(キャリーフラグはボローフラグでもある)、キャリーフラグをクリアする必要はありません。

●減算に対するDAA(十進補正)のまとめ

加算のときと同じように以上のことをまとめてみます。

補正前の数の、
1)下位桁が6〜Fで、かつHフラグが立っている場合は、FAを加算し、加算後にCフラグをクリアする
2)上位桁が6〜Fで、かつCフラグが立っているときは、A0を加算する
3)ただし、1)と2)が同時に成立する場合には、9Aを加算する

2008.7.22upload

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