MPLABを使っているけれど…(ビット操作)

NO IMAGE

最近、MPLABを使ってUSB PICで遊んでいることを書いているけれど、今までSourceBoostCを使っていたけれど、MPLAB with C18コンパイラだと使い勝手が一部違っており、戸惑っている。

ビット操作は、SourceBoostCの場合、clear_bit/set_bitという関数があるだけでなく、porta.1=1;(PORTAの1ビットをセットする)といった記述ができる。

しかーし、MPLAB C18の場合は、そういった関数が存在せず、SFRのみPORTAbits.RA1=1;というような記述ができるそうな。しかし、インラインアセンブラでBSF/BCF命令を使ったり、PORTA|=0x01;とビット演算を使ってやればビット操作ができる。

で、SourceBoostCにあるclear_bit/set_bitの元(boostc.h)を見てみると、

・clear_bitは、(reg) &=~(1<<(bitNumb))
・set_bitは、(reg)|=(1<<(bitNumb))

…という記述がなされている。つまり、bitNumbの数だけ左シフトして、ビット演算するみたい。clear_bitの場合は左シフトしてから反転し、AND(&)を取るということか。

で、実際に

void main(){

int y=0xFF;

clear_bit(y,7);
set_bit(y,7);

asm{

bcf _y,1
bsf _y,1

}
}というプログラムを組んでみた。記述通りであれば、clear_bit/set_bitでは、7回左シフトしてビット演算するはずなのだけれど、実際の結果は次の通り。

…省略…
main_1_y EQU 0x00000020
…省略…
main
MOVLW 0xFF
…省略…
MOVWF main_1_y
CLRF main_1_y+D’1′
MOVLW 0x7F
ANDWF main_1_y,F
BSF main_1_y,7

BSF main_1_y,1
BCF main_1_y,1

あれれ?最適化のお陰かな。気になって、最適化をオフにしたけれど、結果は一緒。うむむむむ。。。。てっきりRLFを8回繰り返してビット操作をするのかと思った。(^o^;)
いい塩梅に修正してくれるのね。
でも、clear_bitの箇所はBCF命令にすれば、もっとサイクル数が少なく済むでないのか。これじゃ今後clear_bitを使うのを躊躇ってしまうな。便利に使えるようboostc.hに変更を加えるかな?

ちなみに、プログラム上の
MOVWF main_1_y
CLRF main_1_y+D’1′
…は、数値をレジスタに入れる時(C言語のint y=0xFF;)に発生するようだけれど、シミュレートする限りではCLRF…の箇所(main_1_yの1つ隣のアドレスをクリアする)は無意味みたい。謎だ。
※実は、SFR以外のレジスタは16ビット処理される場合があるらしく、そのためCLRF命令で1つ後のレジスタをクリアにしてやっているってわけ。アセンブラならしっかり8ビット処理できるのでこういう紛らわしいことは起こらないのだけれど…。(2010.2.13)

※ここの所、PCでC関連の言語を使っていたため、うっかり(unsigned)intを使ってしまったからですな。(unsigned)charを使えば、問題なく8ビット処理できるのです。念のため(2010.2.24)