補講 32ビット演算

目次へ目次へ戻る 32ビットバイナリ

CASL II/COMET IIがサポートしている16ビットの2進数では0〜65535(符号付きなら-32768〜32767)までの数しか表現できません。

もっと大きな数を扱いたい場合はどうしたらよいでしょうか? 16ビットの語をふたつ合わせれば32ビットの数値を表現できます。 ただし、COMET II のハードウェアにはこのような数を扱う命令はありませんので、2語をひとつの32ビット値として扱うようにプログラム側で処理する必要があります。

加算

10進数2桁の足し算をイメージしてください。 1の位同士を足し合わせて桁上がりがあれば10の位に1を加えます。 2語の演算を行う場合もまったく同じです。 下位の語同士を加えて、桁上がりがあれば上位の語に1を加えます。 桁上がりがある場合は必ず1です。2や3が桁上がりすることはありません。 以下は32ビット加算を行うプログラムの例です。

下位からの桁上がりがあるかどうかを符号なし加算のオーバーフローフラグで判断しています。 このサブルーチンは自体は符号なし演算にも符号付き演算にも使えます。 2の補数は負の数でも同じアルゴリズムで加減算できるようにするためのものだからです。 ADDLとADDAの違いはオーバーフローフラグの立ち方だけです。オーバーフローフラグを見ないのであればどちらを使っても実は同じなのです。

減算

減算も同じ理屈です。上のADD32ルーチンの2つのADDLをSUBLに変えて、さらに、OVERというラベルのついた行で1加えているのを1引くように変えることで減算ができます。

符号なし比較

上位側を比べて大小関係があればそれが32ビット値の大小関係です。 上位側が等しい場合だけ下位側の比較を行います。 比較命令を実行したあと、フラグを変える命令を実行しないでリターンすれば、フラグレジスタに残った比較結果をそのまま呼び出し側に渡せます。

符号付き比較

符号付きの場合は上位16ビットの最上位ビットが符号になります。 上位側は符号付きで比較します。 下位側には符号がありませんので、下位側は符号なし比較を行います。

0かどうかのチェック

上位と下位とのすべてのビットが0なら32ビット値はゼロ、ひとつでも0でないビットがあれば32ビット値はゼロではありません。 二語のビットがすべてゼロかどうかを調べるには上位と下位の語のORを取れば一発でわかります。 ORされた結果の数値自体には意味はありませんが、上位、下位の語の中にひとつでも1のビットがあればORした結果は0でない値になります。

1ビット左シフト

上位側の語を左シフトします。そのあと下位側の語を左シフトして、押し出された最上位ビットを上位側の語の最下位ビットに入れてやります。

符号付きであれば、上位側のシフト(SLL GR2,1)だけをSLA命令に変えてやればよいでしょう。

nビットシフト

上のSLLのビット数を増やすだけではいけません。 上のプログラムではオーバーフローフラグで下位から上位への桁あふれをつないでいますが、オーバーフローフラグには1ビットしか入らないためです。 シフトするビット数の回数だけ上のプログラムをループするのが一番簡単ですが、実行効率を重視するなら、上位側、下位側をnビットシフトして、それとは別に 下位から上位へとあふれるビットのパターン(下位側を(16-n)ビット右シフト)を別に生成して、上位側にORしてやるとよいかもしれません。 シフトするのが16ビット以上の場合も考慮しなくてはなりません。

1ビット右シフト

上の左シフトと要領は同じですが、右シフトして上位側からあふれたビットを下位側の最上位ビットにセットする形になります。 そのため、シフトは下位側から行うのがよいでしょう。