「天文屋のためのマイコン入門」条件ジャンプ命令
さて、プログラム構成上、絶対必要なもののうち無条件ジャンプ命令については前回説明しました。しかし、まだ条件ジャンプ命令が残っています。
条件ジャンプ命令のうち、分かりやすい命令を一つ紹介します。
ある演算命令を実行した後に、演算結果が0でないなら、k番地にジャンプする。
このような命令があれば、ある処理を有限回数(無限でない)実行する処理が記述できます。
たとえば、ある処理を10回実行したいとします。
1 まず、汎用レジスに数値10をセットします。
2 そのレジスタの数値を一回処理するごとに1ずつ減らしていきます。
3 もし、その数が0でないなら、処理の最初の番地にジャンプして繰り返す。
さて、前述の条件ジャンプ命令ですが、k番地にジャンプする部分、ここが命令コストが高いのでした、なぜならジャンプ先の番地が必要だからです。そこで、次のような命令を考えます。
演算結果が0なら、次の命令をスキップする
次の命令をスキップとは、次の命令を実行しないで、次の次の命令を実行するということです。この命令は番地を含まないので命令コストは低いです。
このスキップ命令と前回説明した無条件ジャンプ命令を組み合わせれば、最初に説明した条件ジャンプとまったく同等のことができます。
演算結果が0でないなら、k番地にジャンプする。
|| 同等
演算結果が0なら次の命令をスキップ
GOTO k番地
演算結果が0なら、GOTO命令はスキップされます。
演算結果が0でないならGOTO命令が実行されk番地にジャンプします。
つまり、スキップ命令があれば、無条件ジャンプ命令と組み合わせて、様々な条件ジャンプが実現できるのです。
なにやら、面倒な話が続いてすみません。もう少し辛抱してください。さらに面倒なことが続きます。
ここで、演算結果が0かどうかの判断です。実は演算命令を実行した後に、その結果が0かどうかは非常に重要なので、0かどうかを保存して置く場所があります。それをフラグといいます。フラグとは旗という意味です。0なら旗を立てよということです。もっとも実際に立てるのは旗ではなく、ビットです。つまり'1'です。
演算結果が0なら'1'がセットされ、0でないなら'0'にクリアされる特別なビット
これをゼロフラグといい、Zの記号で示します。
さて、このゼロフラグはどこにあるのでしょうか? 実はバンクの説明で出てきたSTATUSレジスタの中にあるのです。
この図の2番目のビットがゼロフラグです。ちなみにDC、Cも違う種類のフラグです。
演算命令を実行した結果が0の場合、Zは'1'にセットされます。
演算命令を実行した結果が0以外の場合は、'0'にクリアされます。
したがって、STATUSレジスタ(3番地でしたね)のビット2を判断できれば0か0でないか判断したことになります。そこで、条件スキップ命令にもどりますが、次のようなスキップ命令があれば0かどうかの判断ができることになります。
演算結果が0なら、次の命令をスキップ
|| 同等
3番地のレジスタの2番目のビット1なら、次の命令をスキップ
やっと、ここで条件ジャンプ命令を定式化することができました。つまり、上の命令を汎用化して次の命令に到着します。
やっと完成した命令
●f番地のレジスタのbビットが1なら、次の命令をスキップ
これの論理を反転した命令も追加します。
●f番地のレジスタのbビットが0なら、次の命令をスキップ
この命令を記号化したのが、そのままPICの命令になります。
これで条件ジャンプ命令が完成しました。これで理論上は何でもできます。例として、同じ処理を10回する例を示します。
番地1 MOVLW 10 ワーキングレジスタに10をセット
番地2 MOVWF 120 120番地の汎用レジスタに10をセット
番地3 処理A ここに繰り返したい処理を記述(何命令でも可)
番地4 DECF 120,F 120番地の汎用レジスタをデクリメント(1を減算)
番地5 BTFSS 3 , 2 STATUSレジスタ(3番地)のビット2が'1'なら、すなわち上記
演算結果が0なら、次の命令をスキップ
番地6 GOTO 3 3番地にジャンプ
次に、120番地の汎用レジスタの値が10の時だけ、処理Aを実行する例を示します。
番地1 MOVF 120,W 120番地のレジスタをワーキングレジスタに転送
番地2 ADDLW -10 ワーキングレジスタから10を引く
番地3 BTFSS 3 , 2 STATUSレジスタ(3番地)のビット2が'1'なら、すなわち上記
演算結果が0なら、(つまりW=10なら)次の命令をスキップ
番地4 GOTO 6 6番地にジャンプ
番地5 処理A
番地6 .....
この例ですが、W=10なら、GOTO 6がスキップされますので、処理Aが実行されます。またこの例ですが、処理Aが1命令なら、次のように簡略化されます。
番地1 MOVF 120,W 120番地のレジスタをワーキングレジスタに転送
番地2 ADDLW -10 ワーキングレジスタから10を引く
番地3 BTFSC 3 , 2 STATUSレジスタ(3番地)のビット2が'0'なら、すなわち上記
演算結果が0でないなら、(つまりW=10でないなら)次の命令 をスキップ
番地4 処理A
番地5 .....
この場合、スキップされるのは、GOTO命令ではなく処理Aです。スキップ命令は何も、GOTO命令とセットで使う必要はまったくありません。
もっとも、処理Aが2命令以上なら、GOTOと併用しなければなりません。
最後に便利な命令を紹介しておきます。
スキップ命令は例題1のようにデクリメント命令の直後に利用されることが多いです。そこで、これら一連の命令を一つにした命令があります。
この便利な命令を使うと、例題1は次のようになります。
番地1 MOVLW 10 ワーキングレジスタに10をセット
番地2 MOVWF 120 120番地の汎用レジスタに10をセット
番地3 処理A ここに繰り返したい処理を記述(何命令でも可)
番地4 DECFSZ 120,F 120番地の汎用レジスタをデクリメント、結果が0なら次の
命令をスキップ
番地5 GOTO 3 3番地にジャンプ
DECFSZ命令には実は、インクリメントバージョンもありますが、あまり使用頻度は高くないと思い、紹介は割愛しました。
これでPICの命令とデータに関する基本のなが~い、なが~い説明が終わりました。お疲れ様でした。まだまだ説明不足のところもありますが、とりあえず終わりにします。それ以外に必要な知識は必要な時に説明します。
一通り基本の説明が終わったので、次回、まとめをします。その後、実際のプログラムの説明をしたいと思います。
| 固定リンク
コメント