HI-TECH software PICC compiler

PICのアセンブラは一通り見てみたので、本格的なプログラム開発というとやはりCを使いたいと思う。最近MPLAB IDEにはHI-TECH softwareのPICCコンパイラ(V9.60あたりから正式にはHI-TECH C PRO for the PIC10/12/16 MCU Familyに変わったようだ)が附属している。ネットを見る限りコンパイラとしての評判も良いようです。
Lite modeでは制限があるが、私の書くプログラムの規模であれば問題はなさそう。
というわけで、しばらくはPICCを使って開発を行なってみようと思うが幾つか気づいた点があったので御参考まで。

MPLAB SIMでは変数の値やアドレスが見れますが、Cで開発するとこれがみれません。
少々面倒ですが、コンパイルした時に生成されるmapファイルで変数のポインタを確認しておき、これをMPLAB SIMでWatch対象とすることでワークアラウンドになります。
mapファイルのSymbol Tableでは_<関数名>_<変数名>という命名規則になっているようです。例えば、次の例ではソース中で
void Puts_LCD4(char *ptr)
と宣言されています。
                                  Symbol Table

??_Puts_LCD4       fnauto0     0012  ??_main            fnauto0     000C
?_Puts_LCD4        fnauto0     0012  ?_main             fnauto0     000C
				  :
				  :
_PS1               (abs)       0409  _PS2               (abs)       040A
_PSA               (abs)       040B  _Puts_LCD4         text9       03E6
_Puts_LCD4_ptr     fnauto0     0012  _RA0               (abs)       0028
				  :
				  :

文字列を宣言する際に、関数の頭で配列に入れずに、文字列をダブルクォーテーションで括って直接引数として渡すと、メモリ上に文字列が格納されずにNULLが渡されるようだ。
例えば、次のようなプログラムは動かない。
void Puts_LCD4(char *ptr){
    while(*ptr){
        PORTB=*ptr++;
    }
}
void main(void){
    GIE=0;
    TRISB=0x0;

    Puts_LCD4("Test");
}
このようにすると問題無く動作する。
void main(void){
    char buf[]="Test";
    GIE=0;
    TRISB=0x0;

    Puts_LCD4(buf);
}
HI-TECH softwareに聞いてみたところ、これは9.60PL4で修正されているバグだそうです。私はPL3を使っていたのですが、PL5にしてみたところ動作するようになりました。

PICはメモリが少ないため、bit型がサポートされているが、これは引数として渡すことは出来ない模様。次のようなコードをコンパイルすると、エラーになります。
function(bit a){
        :
}
main(){
    function(0);
}
内部動作を考えると仕方ないかなという気もしますが。

MPLAB IDEの'Disassembly list'画面で最終行画表示されていないようだ。 例えば次のようなソースで試すと、
void main(void){
    PORTD=0;
    while(1){
    PORTD--;
    }
}
次のようなdisassembly listが生成されるのだが、アドレス0018にあるはずの'SUBWF PORTD, F'命令が表示されない。
  :
  :
18:                    PORTD=0;
  0010    1003     BCF STATUS, 0
  0011    1283     BCF STATUS, 0x5
  0012    1303     BCF STATUS, 0x6
  0013    3000     MOVLW 0
  0014    1803     BTFSC STATUS, 0
  0015    3001     MOVLW 0x1
  0016    0088     MOVWF PORTD
19:                    while(1){
  0019    2817     GOTO 0x17
  20:                    PORTD--;
  0017    3001     MOVLW 0x1
  <-- ここが抜けている
表示されていないだけで、シュミレーションは正しく動作する。

asm()でソースコード中で任意のアセンブラコードを使用することができるが、この関数はマクロ中で使用することは出来ないようだ。コンパイルエラーも発生しないので要注意。 例えば、次のようなコードを作成するために、
BSF PORTB, 0
NOP
BCF PORTB, 0
このようなソースを書くと、
#include 
#define STROBE_DELAY(x) (x)=1;asm("nop");(x)=0

__CONFIG(HS & WDTDIS & PWRTEN & BOREN & LVPDIS & DUNPROT & WRTDIS & DEBUGDIS & UNPROTECT);

void main(void){
    TRISB=0;
    STROBE_DELAY(RB0);
}
次のようなコードが生成される。asm()以降の命令しか解釈していない模様。
12:                    STROBE_DELAY(RB0);
  000A    1283     BCF STATUS, 0x5
  000B    1303     BCF STATUS, 0x6
  000C    1406     BSF PORTB, 0
LCDへのデータ読み込みなどの用途で使用できると結構便利な気がするのですが。関数にするほどでもないし。