2008/05/24

PICの小技: ブロックif

PICのアセンブラで条件分岐の処理を書くのって大変ですね。
条件を何重にも「否定」で考えないといけないし、
いちいちユニークなラベルを作るのもめんどくさいし、
elseがあったり多重になってくると、もうワケ分かりません。
Cみたいに if ... { ... } って書けると便利なんだけどなぁ...

実は、MPASMのマクロだけで、それっぽいことができるんです。
; マクロで使う変数の初期化
variable _BLK_count = 0
variable _BLK_depth = 0

; ifの素。条件スキップ命令と組み合わせて使う
if_n_ macro
_BLK_count++
_BLK_depth++
_BLK_stack#v(_BLK_depth) = _BLK_count
goto _BLK_label#v(_BLK_count)
endm

; elseブロック。あってもなくても良い
_else_ macro
goto _BLK_label#v(_BLK_stack#v(_BLK_depth)+1000)
_BLK_label#v(_BLK_stack#v(_BLK_depth)):
_BLK_stack#v(_BLK_depth) = _BLK_stack#v(_BLK_depth)+1000
endm

; ブロックの終わり
_endif macro
_BLK_label#v(_BLK_stack#v(_BLK_depth)):
_BLK_stack#v(_BLK_depth) = 0
_BLK_depth--
endm

このままでも使えますが、もっと分かりやすくするために、
分岐条件とif_n_を組み合わせたマクロを作っておくと便利です。
「スキップする条件」=「ifブロックを実行する条件」になるので、
例えば、Zフラグを条件とする場合は、こうなります。
if_z_   macro
btfss STATUS,Z
if_n_
endm

これで、こんな書き方ができるようになります。
        movf    MODE,W
xorlw 0x01
if_z_
movf N2,W
addwf N1,F
_else_
movf N1,W
if_z_
movlw 1
_endif
subwf N2,F
_endif

・インデントはお好みで。
・_else_はあってもなくてもかまいません。
・もちろん何重にもネストできます。

0 件のコメント: