C++言語のオーバーフローメモ

前回の記事で、NESエミュレータをSDLとC++言語で作り始めました。
私は素人なので難しい構文は知りません。そのためCPUの命令を256個switch文で書いてます。いいやり方あるんでしょうか・・・

とりあえず、書いているときにちょっとオーバーフローについて不安になったことのメモ。
例えば、

Uint8 uint8a = 0b1111’1111;
Uint8 uint8b = 0b1111’1111;
Uint16 uint16c = 0b0000’0000’0000’0000;

というように、8bitの変数2つと16bitの変数1つを用意します。(0bは2進数を書くときに使います。また、桁が分かりやすくなるように 「 ’ 」という記号を使うことができます。)
ここで、

uint8a = uint8a + uint8b;
uint16c = (Uint8)( uint8a + uint8b )
uint16c = uint8a + uint8b;

という計算をしたら、uint8aやuint16cに入る値はそれぞれ何でしょうか。
もしオーバーフローをしなかったら、 0x1FF になります(0xは16進数を書くときに使います。)
しかし、8bitからオーバーフローをしたら0xFF になります。桁があふれてしまいます。
まあ、windowsに標準でついているプログラマー電卓などの電卓で計算してみてください。

実際に

std::cout << std::hex << (int)uint8a << std::endl;
std::cout << std::hex << uint16c << std::endl;

などと表示するようにしたら、それぞれの計算結果は次のように表示されます。

FF
FF
1FF

つまり、Uint8同士の計算だったとしても、Uint16の変数(上の例ならuint16c)に計算結果を代入するならばオーバーフローをしないようです。
オーバーフローをしてほしいときは、計算結果をUint8にキャストすることを明示しないといけないみたいですね。

この計算を使う場面はアドレッシングモードです。例えば(Zeropage,X)というアドレッシングモードは、ゼロページアドレスにXレジスタを足したアドレスを対象とします。しかし、このゼロページアドレスにXを足したアドレスがページ境界を超えた場合、ゼロページ内でループします。例を挙げましょうか。Zeropageが$FFで、Xが$#2の場合、このアドレッシングモードで対象となるアドレスは$(FF+2) = $101となりそうですが、実際は3桁目がオーバーフローして$01になるってことですね。
この仕組みは上述の8bitキャストを使ってオーバーフローを意図的に起こしてやれば簡単に実装できます。

Uint8 Zeropage; //ゼロページアドレス。
Uint8 X; //Xレジスタは8bitです。
Uint16 Address = (Uint8)(Zeropage + X);

というイメージです。もちろんゼロページアドレスは命令のオペランドであり、XはXレジスタのことですが。

しかし、こんな細かいこと、プログラムで書き間違えたら後で見つけるの非常に面倒そうですね…
ただでさえ256個もcase使ってばらばらに書いているのにorz

コメント

タイトルとURLをコピーしました