落合正弘さん作のPICマイコン用アセンブラ「PA (Ver3.05)」
でマクロを使うときの注意   ・・・PAの落とし穴

2005-03-11

マクロ使用時の注意

 PICマイコンを使った私の製作物、すべて落合正弘さん作のアセンブラ「PA」を使用しています。
PICを使いはじめてだいぶ経つのですが、いまだにマイクロチップのニーモニックは馴染めません。
PAには独自の拡張ニーモニックがあらかじめ用意されているので、さほどの違和感無く便利に使わせてもらっています。
なにより「MS-DOS」で動くのがありがたいのです。
PICマイコンごときのプログラム開発にWindowsは要りません。(と、強がりを書いておきます)
PAはマクロも備えているので、独自の処理を記述するときなど、便利に使えます。

さて、愛用していますPA、ちょっとした落とし穴に出会いましたので注意点を報告しておきます。

 PAのマクロでビット指定したデータを使うときは、先に確定したアドレスに対してビット位置の指定をしなければなりません。
アドレスがまだ確定していないデータに対してビット位置を指定してしまうと、マクロ内でそのビットデータに対する実行コードが展開されないという異状が生じます。
この異状、残念ながらエラーメッセージとしての警告が出ないので、気がつくのにたいへん苦労します。
Pass1とPass2でラベルの位置にズレが生じるので、Phaseエラーとして警告が出てもよさそうなのですが、現PAでは警告が出ませんのでやっかいなのです。

異状の発生するプログラムを紹介しておきます。

(プログラムリストは等倍フォントでご覧ください)

;***** 落合正弘さん作のPICアセンブラ PA    *****
;    におけるマクロ使用の注意

;*   チップ名指定
        .16f84         ;仮に指定
;*   configuration bit (必須)
_fuse@     equ   2007h      ;とりあえずincファイルは使わない
_data@     equ   2100h

;***** マ ク ロ   *****
;*   return bit on
retb  macro  b
    btfsc  b            ;bit off ならスキップ
    return             ;指定したビットがオンでリタ-ンするマクロ
    endm

;*   フラグ ビット指定(データ出現の前に指定)
f_ng  equ   f_00.0     ;NG flag この出現位置に注目

;***** RAMデータエリア   *****
    org   20h
f_00:  ds   1        ;flag 0 data ビット指定するデータ

;*   フラグ ビット指定(データ出現の後に指定)
f_ok  equ   f_00.1     ;OK flag ←《1》データが出現した後に指定

;***** プログラムエリア    *****
    org   0            ;ここからROM内

    goto  a1       ;ジャンプアドレスに注目
    goto  a2
    goto  a3       ;★   このジャンプ先を注目
    nop
a1:               ;0004
    retb  f_ok      ;    これはok
a2:               ;0006
    retb  f_ng      ;★   これがうまくアセンブルされないのだろう
a3:               ;0008
    nop
    goto  a1
    goto  a2
    goto  a3       ;    上を参照するこれはok
;---------------------------
;    以降の後方参照でアドレスが狂ってしまう
    goto  b1       ;★   アドレスが狂う
    nop
b1:               ;000E
    nop
    goto  b1       ;    上を参照するこれはok

;    《1》の「f_ok」のようにデータが出現してからビット位置を
;    指定するようにしなければならない。
;    f_ngのようにデータ位置が確定していないままビット位置を指定した
;    場合それを使った外部マクロがアセンブルされコードが生成されない
;    のではないだろうか。
;    本来なら「phaseエラー」(pass1とpass2で生成したアドレスが異なる)
;    あたりが出てくれてよさそうなのだが。

 以下はそのアセンブルリストです。
行番号と不要行、コメントの一部を削っています。
「goto a3」と「goto b1」と書いている所に注目してください。
「a3」「b1」のアドレスと異なる場所に飛んでいくコードが生成されています。
ビット指定を使って指定したフラグ「f_ng」に対する実行コードが、パス1で生成されな
いために、パス1とパス2で異なったラベルのアドレス値が発生しているのです。
このせいで、作ったプログラムが暴走します。

            ;*   フラグ ビット指定(データ出現の前に指定)
=0020.0         f_ng  equ   f_00.0     ;NG flag
            
            ;***** RAMデータエリア   *****
0020              org   20h
0020          f_00:  ds   1        ;flag 0 data
            
            ;*   フラグ ビット指定(データ出現の後に指定)
=0020.1         f_ok  equ   f_00.1     ;OK flag 《1》
            
            ;***** プログラムエリア    *****
0000              org   0
            
0000 2804           goto  a1
0001 2806           goto  a2
0002 2806           goto  a3       ;★   これはおかしい
0003 0000           nop
0004          a1:               ;0004
0004 18A0 0008         retb  f_ok      ;    これはok
0006          a2:               ;0006
0006 1820 0008         retb  f_ng      ;★   これがNG
0008          a3:               ;0008
0008 0000           nop
0009 2804           goto  a1
000A 2806           goto  a2
000B 2808           goto  a3       ;    これはok
            ;---------------------------
            ;    以降の後方参照でアドレスが狂ってしまう
000C 280C           goto  b1       ;★   アドレスが狂う
000D 0000           nop
000E          b1:               ;000E
000E 0000           nop
000F 280E           goto  b1       ;    上を参照するこれはok
            
-- Symbol List --
_fuse@         : 2007
_data@         : 2100
f_00          : 0020
f_ok          : 0020.1
a1           : 0004
a2           : 0006
a3           : 0008
b1           : 000E
f_ng          : 0020.0
 パス2ではちゃんとコードが生成されるのでアドレスに狂いは生じません。
ところがパス1では、まだ生成すべきデータが確定していないということなのでしょう、実行コードが作られないようなのです。
このためプログラムの下のほうにあるラベルにジャンプするアドレスに狂いが生じ、プログラムが思い通りに動かなくなってしまいます。
マクロを使ったときだけの異状のようですし、《1》のように記述すれば解決できますので、致命的ではありません。
ただ、こんなことがあるということを知っておかないと、原因追求と解決に往生します。


 落合正弘さん作のアセンブラ「PA-3.0.5」、
http://www.tristate.ne.jp/picnic/menu.html
にあります。

また、PICマイコンの自家製書き込みツール(MS−DOS用)は
PICマイコン書き込みツール
で、紹介しています。