隣のビットを操作する訳

NO IMAGE

MPLAB C18をいじっていて気になったことがある。
変数を足し算でカウントしていき、255から0になった際、STATUSレジスタのC(キャリー)ビットを使い桁上げを行うというプログラムを作ったのだけれど、どうも様子がおかしい…。

アセンブラでプログラムを組んでいた時は255(FF)から0になった際、STATUSレジスタのCフラグが1になるのだけれど、C言語の場合はなぜか1にならない。うーん。

初めは理由は分からなかったけれど、その部分だけ取り出してコンパイル。シミュレーションしてレジスタの様子を見て、その理由が分かった。

どうも、C18の場合はSFR以外は16ビットとして処理するらしく、255(FF)からインクリメントすると、そのレジスタは0になるものの1つ後のアドレスがインクリメントされるのだ。16ビット扱いなので、当然キャリーは発生しない。設定したレジスタと1つ後のレジスタがFFとなり、更にインクリメントすると全て0になると共にDC/C/Zフラグが1になるのはどうよ?
この現象、SourceBoostのBoostCも同じだった。8ビットマイコンなら8ビットらしくしてくり~。

実は、変数をカウントしていき、その値をPORT*に代入し、出力させるというプログラムを作っているのだけれど、先のような現象のせいでアセンブラで簡単にできるものがちと難しくなりそう。
いえね。USBも使うのでアセンブラを使いたくても使えないのですよ。わっはっは。(^o^;)

色々試行錯誤考えていたら、足し算(INCF)の部分だけインラインアセンブラを使う方法を思いついた。こうするとちゃんと8ビット扱いにしてくれ、C/Zフラグも使い放題。しかも、簡単!
でも、変数のアドレス設定は相変わらず2個飛ばしで設定してくれる。何たる無駄な。

※MicrochipからDS51288J_JPなるマニュアルを入手。どうも、(unsigned)intは16ビットになるらしく、8ビットにしたければ、(unsigned)charにすればいいらしい。SourceBoostCでもそうだった。なーんだ。(^o^;)こうすればインラインアセンブラを使って変な小細工をしなくていいよな。それに、途中インラインアセンブラを使うと、Cの部分で設定した変数(アドレス)でなく、変なアドレスでごにょごにょやるみたい。うーーーん。(2010.2.15)