PICアセンブラにおける分岐/ループ処理の組み立て方(基本編)

C言語では、if,switchによる分岐や、for,whileによる繰り返し命令を持っています。
一方、PICのアセンブラはどうかというと、当然ながらそんな便利な制御機能は持っていません。

というか、PICに限らずほぼ全てのCPUは、機械語レベルで上記のような繰り返し処理を持っていません。

それでは、アセンブラレベルでどうやって制御構造を組み立てていくかというと、条件付分岐命令というものを利用していきます。



PICのアセンブリにおいて、条件付き分岐を行える命令は以下の4つです

BTFSC   ; bit test file-reg skip if clear
BTFSS   ; bit test file-reg skip if set
DECFSZ  ; decrement file-reg skip if zero
INCFSZ  ; increment file-reg skip if zero



各命令の意味を日本語で書くと、以下のような感じになります。説明文が”xxxならスキップ”となっていることからも分かるように、全て条件によって処理を分岐させる事が出来ます。

BTFSC   ; レジスタの指定したビットが0なら次の命令をスキップ
BTFSS   ; レジスタの指定したビットが1なら次の命令をスキップ
DECFSZ  ; レジスタ値を1減算し,値が0なら次の命令をスキップ
INCFSZ  ; レジスタ値を1加算し,値が0なら次の命令をスキップ




PICのアセンブリで分岐やループを行いたい場合は、これらの命令がもつ条件付スキップの機能を活用して条件分けを行っていきます。



分岐処理の基本形


例1: Wレジスタの最上位ビットが立っていたら処理を行う


条件に一致するときのみ処理(シフト演算)を行う処理です。

SUBLW   0x80
BTFSC   STATUS, Z   ; ゼロフラグをチェック
RRF     PORTB, F    ; Z = 0の場合の処理 (右シフト)
NOP                 ; Z = 1の場合



これは、Cで書くとこんな感じになります。

if ( wreg - 0x80 == 0 ) {
    portb = portb < 1;
}



例ではWレジスタの値が0x80だったら、PortBの値を左シフトするという処理を行っています。
レジスタの値の判定にはSUB命令を使用し、Wレジスタから0x80(10進で112)を引いて、その値が0だったときのみ後続の処理を行わせています。

この例はC言語でいう”if文”の2分岐処理になります。
C言語での分岐には、他にswitchによる複数の分岐がありますが、上記の処理を書き連ねていくと可読性が悪くなるので、テーブルジャンプという仕組みを使うと分かり易いです。
この辺の詳細はまた改めて説明します。


ループ処理の基本形


例2: 指定された回数だけループ処理を行う

こちらの例では、60回のループ処理を行っています。

CNT1 EQU    0x20    ; ループカウンタの保存先
 
    MOVLW   60      ; ループカウンタに初期値をセット
    MOVWF   CNT1
LOOP
    RRF     PORTB   ; 処理内容
 
    DECFSZ  CNT1    ; ループを抜けるべきか判定する
    GOTO    LOOP
    NOP             ; ループ後の処理



C言語で書くと以下のようなロジックになります。

for ( cnt1 = 60; cnt1 < 0; cnt1-- ) {
    portb = portb < 1;
}




PICでタイマー制御を行いたい場合、基本的な考え方は上記のループを活用します。
具体的には、ループ内でnopを実行し空回しすることで、所定時間の”待ち”を作ることが多いです。

タイマー制御に関して知りたい場合は、以下の記事が参考になります。
PICで一定時間のスリープ(ウェイト)を行う

関連記事

コメントを残す

メールアドレスが公開されることはありません。