PAアセンブラのインストラクション(命令一覧)

PAアセンブラにはオリジナルのPICマイコンの命令以外にこのアセンブラ独自の拡張命令があります。 拡張といってもPICマイコンの命令の他に新たに命令が作れるという訳ではなく下記の命令を使用した場合、 主に複数の命令に展開されてコーディングができるという考え方です。
これで数値の比較や他のページへのコールなどが容易に行えるなどのメリットがあります。しかし、 他のアセンブラでは使用できないとか他のプログラマが理解できないというデメリットもあります。

加算 add fr1,fr2
add fr,W
add W,fr
addb fr,bit
論理積 and fr,#lite
and fr1,fr2
and fr,W
and W,#lite
and W,fr
条件ジャンプ cja fr,#lite,addr9
cja fr1,fr2,addr9
cjae fr,#lite,addr9
cjae fr1,fr2,addr9
cjb fr,#lite,addr9
cjb fr1,fr2,addr9
cjbe fr,#lite,addr9
cjbe fr1,fr2,addr9
cje fr,#lite,addr9
cje fr1,fr2,addr9
cjne fr,#lite,addr9
cjne fr1,fr2,addr9
フラグ設定 clc
クリア系 clr fr
clr w
clr wdt
clrb bit
フラグ設定 clz
条件スキップ csa fr,#lite
csa fr1,fr2
csae fr,#lite
csae fr1,fr2
csb fr,#lite
csb fr1,fr2
csbe fr,#lite
csbe fr1,fr2
cse fr,#lite
cse fr1,fr2
csne fr,#lite
csne fr1,fr2
-1減算系命令 dec fr

-1減算系命令 decsz fr
djnz fr,addr9
+1加算系命令 ijnz fr,addr9
inc fr
incsz fr
ジャンプ系命令 jb bit,addr9
jc addr9
jmp addr9
jmp pc+w
jmp w
jnb bit,addr9
jnc addr9
jnz addr9
jz addr9
lcall addr11
ljmp addr11
lset addr11
MOV系命令 mov fr,#lite
mov fr1,fr2
mov fr,W
mov option,#lite
mov option,fr
mov option,W
mov !port_fr,#lite
mov !port_fr,fr
mov !port_fr,W
mov W,#lite
mov W,fr
mov W,/fr
mov W,fr-W
mov W,++fr
mov W,--fr
mov W,<
mov W,>>fr
mov W,<>fr
movb bit1,bit2
movb bit1,/bit2
movsz W,++fr
movsz W,--fr
符号反転 neg fr
反転 not fr
not W
論理和 or fr,#lite
or fr1,fr2
or fr,W
or W,#lite
or W,fr
リターン系 ret
retw lite1[,lite2,lite3...]
シフト rl fr
rr fr
スキップ系 sb bit
sc
ビット処理 setb bit
スキップ系 skip
snb bit
snc
snz
フラグ設定 stc
stz
減算命令 sub fr,#lite
sub fr1,fr2
sub fr,W
subb fr,bit
入れ替え swap fr
スキップ系 sz
0チェック test fr
test W
排他的論理和 xor fr,#lite
xor fr1,fr2
xor fr,W
xor W,#lite
xor W,fr

add fr,#lite C,Z,DC
ファイルレジスタfrと定数liteを加算して結果をfrに戻します。 実行クロックは2サイクルです。 演算結果に応じてC,Z,DCフラグが変化します。
<内部動作>
movlw lite
addwf fr,1

add fr1,fr2
ファイルレジスタfr1とfr2を加算して結果をfr1に戻します。 実行クロックは2サイクルです。 演算結果に応じてC,Z,DCフラグが変化します。
<内部動作>
movf fr2,0
addwf fr1,1

add fr,W
ファイルレジスタfrとWを加算して結果をfrに戻します。 実行クロックは1サイクルです。 演算結果に応じてC,Z,DCフラグが変化します。
<内部動作>
addwf fr,1

add W,fr
ファイルレジスタfrとWを加算して結果をWに戻します。 実行クロックは1サイクルです。 演算結果に応じてC,Z,DCフラグが変化します。
<内部動作>
addwf fr,0

addb fr,bit
bitで指定したビットが1のときファイルレジスタfrに1を加算します。 0の時は何もしません。実行クロックは2サイクルです。 フラグは変化しません。
<内部動作>
btfsc bit
incf fr,1

and fr,#lite
<内部動作>
movlw lite
andwf fr,1

and fr1,fr2
<内部動作>
movf fr2,0
andwf fr1,1

and fr,W
<内部動作>
and fr,1

and W,#lite
<内部動作>
andlw lite

and W,fr
<内部動作>
and fr,0

cja fr,#lite,addr9
(Compare Jump Above) ファイルレジスタと定数を比較して条件が真ならジャンプします。 fr > liteの時ラベルで指定したアドレスにジャンプします。
<内部動作>
movlw lite ^ 0ffh
addwf fr,0
btfsc 3.0
goto addr9

cja fr1,fr2,addr9
(Compare Jump Above) ファイルレジスタと定数を比較して条件が真ならジャンプします。 fr1 > fr2の時ラベルで指定したアドレスにジャンプします。
<内部動作>
movf fr1,0
subwf fr2,0
btfss 3.0
goto addr9

cjae fr,#lite,addr9
ファイルレジスタと定数を比較して条件が真ならジャンプします。 fr >= liteの時ラベルで指定したアドレスにジャンプします。
<内部動作>
movlw lite
subwf fr,0
btfsc 3.0
goto addr9

cjae fr1,fr2,addr9
<内部動作>
movf fr2,0
subwf fr1,0
btfsc 3.0
goto addr9

cjb fr,#lite,addr9
<内部動作>
movlw lite
subwf fr,0
btfss 3.0
goto addr9

cjb fr1,fr2,addr9
<内部動作>
movf fr2,0
subwf fr1,0
btfss 3.0
goto addr9

cjbe fr,#lite,addr9
<内部動作>
movlw lite ^ 0ffh
addwf fr,0
btfss 3.0
goto addr9

cjbe fr1,fr2,addr9
<内部動作>
movf fr1,0
subwf fr2,0
btfsc 3.0
goto addr9

cje fr,#lite,addr9
<内部動作>
movlw lite
subwf fr,0
btfsc 3.2
goto addr9

cje fr1,fr2,addr9
<内部動作>
movf fr2,0
subwf fr1,0
btfsc 3.2
goto addr9

cjne fr,#lite,addr9
<内部動作>
movlw lite
subwf fr,0
btfss 3.2
goto addr9

cjne fr1,fr2,addr9
<内部動作>
movf fr2,0
subwf fr1,0
btfss 3.2
goto addr9

clc
<内部動作>
bcf 3.0

clr fr
ファイルレジスタfrを0にクリアします。 Zフラグが1にセットされます。実行クロックは1サイクルです。
<内部動作>
clrf fr

clr w
Wレジスタをクリアします。それだけです。 Zフラグが1にセットされます。
<内部動作>
clrw

clr wdt
内部のウォッチドックタイマ・カウンタをクリアします。
<内部動作>
clrwdt

clrb bit
<内部動作>
bcf bit

clz
<内部動作>
bcf 3.2

csa fr,#lite
<内部動作>
movlw lite ^ 0ffh
addwf fr,0
btfss 3,0

csa fr1,fr2
<内部動作>
movf fr1,0
subwf fr2,0
btfsc 3.0

csae fr,#lite
<内部動作>
movlw lite
subwf fr,0
btfss 3.0

csae fr1,fr2
<内部動作>
movf fr2,0
subwf fr1,0
btfss 3.0

csb fr,#lite
<内部動作>
movlw lite
subwf fr,0
btfsc 3.0

csb fr1,fr2
<内部動作>
movf fr2,0
subwf fr1,0
btfsc 3.0

csbe fr,#lite
<内部動作>
movlw lite ^ 0ffh
addwf fr,0
btfsc 3.0

csbe fr1,fr2
<内部動作>
movf fr1,0
subwf fr2,0
btfss 3.0

cse fr,#lite
<内部動作>
movlw lite
subwf fr,0
btfss 3.2

cse fr1,fr2
<内部動作>
movf fr2,0
subwf fr1,0
btfss 3.2

csne fr,#lite
<内部動作>
movlw lite
subwf fr,0
btfsc 3.2

csne fr1,fr2
<内部動作>
movf fr2,0
subwf fr1,0
btfsc 3.2

dec fr
<内部動作>
decf fr,1

decsz fr
<内部動作>
decfsz fr,1

djnz fr,addr9
 ファイルレジスタfrから1を減算して、結果が0以外のとき、ラベルaddr9で示される アドレスにジャンプします。上記以外のときは次の命令に移ります。  この命令は、プログラム中のループ(for..nextに相当)によく使用されます。 たとえば100回のループを組む場合はこのようにします。 ;**************************************** org 10h cn ds 1 org 0 test mov cn,#100 ; 変数に初期値100を代入します。 loop1 nop ; この命令を100回実行します。 djnz cn,loop1 ;****************************************  この命令を使うことで、プログラムがすっきりし、見やすくなります。 上記のプログラムのcnに好きな値を入れればその回数分ループを繰り返す訳です。 cnは8ビットですから0〜255までの値がとれますが、0を入れた場合はループは 256回繰り返されますので、注意してください。
<内部動作>
decfsz fr,1
goto addr9

ijnz fr,addr9
 ファイルレジスタfrに1を加算して、結果が0以外のとき、ラベルaddr9で示される アドレスにジャンプします。上記以外のときは次の命令に移ります。 この命令はdjnz命令と反対に1を加算して、結果によってジャンプする命令ですが、 通常この命令を使うとややこしくなるので普通は使いません。djnzと対象的に設けられた 命令です。
<内部動作>
incfsz fr,1
goto addr9

inc fr
ファイルレジスタfrに1を加算します。frがFFhの時に1を加算したときは 結果が0になります。実行クロック数は1サイクルです。 注意:この命令によってフラグ(ステータスレジスタフラグ)は変化しません。 フラグを変化させるには、 add fr,#1 と、コーディングしてください。(実行クロックは2サイクルとなります)
<内部動作>
incf fr,1

incsz fr
<内部動作>
incsz fr,1

jb bit,addr9
<内部動作>
btfsc bit
goto addr9

jc addr9
<内部動作>
btfsc 3.0
goto addr9

jmp addr9
ラベルaddr9で示されるアドレスに無条件ジャンプする命令です。
内部的にはgoto命令に置き換えられるので、jmpとgotoは全く同一の処理をします。
<内部動作>
goto addr9

jmp pc+w
PCの値にWレジスタの値を加算して、Wレジスタの値に応じてプログラムを分岐 させることができます。 この命令は配列テーブルや文字列テーブルから
<内部動作>
addwf 2,1

jmp w
<内部動作>
movwf 2

jnb bit,addr9
<内部動作>
btfss bit
goto addr9

jnc addr9
<内部動作>
btfss 3.0
goto addr9

jnz addr9
<内部動作>
btfss 3.2
goto addr9

jz addr9
<内部動作>
btfsc 3.2
goto addr9

lcall addr11
この命令はPIC16C5X専用に用意されています。 16C5Xではcall命令で指定できるアドレスは、アドレスの下位8ビットだけで call命令を実行すると、A0〜7は命令からセットされ、A8は0(固定)にセット、 A9,10はステータスレジスタのPA0,1が暗黙のうちに移動されます。 (こういう、アーキテクチャはプログラムしにくいので止めてほしい>マイクロチップ) A8が0に固定なので、一部コール不能な領域があります。このせいでサブルーチンの 書き方にコツがいります。 上位ビットのPA0,1をプログラマが管理していないとどっか違うバンクのサブルーチンに 飛んでいってしまいします。これが面倒なので、この命令を用意しました。 この命令は始めにPA0,1のビットをコールするアドレスに合わせて自動的に セットして、その後call命令を生成します。これで、上位ビットを気にせず サブルーチンコールできます。 A8が1のアドレスに飛ぼうとすると、アセンブルエラーになります。 この命令と併用してlset命令も必ず使用するはずです。そちらも参照してください。
<内部動作>
bcf/bsf 3,x
bcf/bsf 3,x
call addr11

ljmp addr11
この命令はPIC16C5X専用に用意されています。 16C5Xではcall命令で指定できるアドレスは、アドレスの下位9ビットだけで call命令を実行すると、A0〜8は命令からセットされ、 A9,10はステータスレジスタのPA0,1が暗黙のうちに移動されます。 (こういう、アーキテクチャはプログラムしにくいので止めてほしい>マイクロチップ) 上位ビットのPA0,1をプログラマが管理していないとどっか違うバンクのサブルーチンに 飛んでいってしまいします。これが面倒なので、この命令を用意しました。 この命令は始めにPA0,1のビットをコールするアドレスに合わせて自動的に セットして、その後call命令を生成します。これで、上位ビットを気にせず サブルーチンコールできます。 この命令と併用してlset命令も必ず使用するはずです。そちらも参照してください。
<内部動作>
bcf/bsf 3,x
bcf/bsf 3,x
goto addr11

lset addr11
この命令はPIC16C5X専用に用意されています。 アドレスaddr11で指定したビット(A9,10)の値に応じて、PA0,1の値を セットします。A0〜8のビットは無視します。この命令で何をするのかというと こういう理由からです。 lcallを使って他のバンクにコールする。 (PA0,1が(他のバンクの)サブルーチンのアドレスに設定されます) ↓ その(他のバンクの)サブルーチンからリターンする。 ↓ call命令でPCと同じバンク内のサブルーチンにコールする。 (call命令はPA0,1を暗黙の内に参照する。しかし、最初のlcall命令でPA0,1は 他のバンクを指してしまっている。コールするとおかしなところに飛んでしまう。) ↓ 暴走する。 この問題を回避するにはcall,jmp(goto)命令を使わず、lcall,ljmp命令のみ使用して、 コール・ジャンプすればいいのですが、同じバンク内のアドレスに何回もコールする場合 PA0,1のビットを設定する命令が多くなりプログラムの無駄が生じます。 lcall <他のバンクのアドレス> ;他のバンクにPA0,1を設定します。 lcall <PCと同じバンク内のアドレス> lcall <PCと同じバンク内のアドレス> lcall <PCと同じバンク内のアドレス> lcall <PCと同じバンク内のアドレス> lcall <PCと同じバンク内のアドレス> そこで、lset命令を使い lcall <他のバンクのアドレス> ;他のバンクにPA0,1を設定します。 lset $ ;この命令でPA0,1をPCと同じに設定し直す。 ;(PCをPA0,1との同調をとる) call <PCと同じバンク内のアドレス> call <PCと同じバンク内のアドレス> call <PCと同じバンク内のアドレス> call <PCと同じバンク内のアドレス> call <PCと同じバンク内のアドレス> このようにすることで、8ワード分命令数が少なくてすみます。
<内部動作>
bcf/bsf 3,x
bcf/bsf 3,x

mov fr,#lite
<内部動作>
movlw lite
movwf fr

mov fr1,fr2
<内部動作>
movf fr2,0
movwf fr1

mov fr,W
<内部動作>
movwf fr

mov option,#lite (move option register)
PIC内部のoptionレジスタに定数liteを設定します。 定数liteの値によっては、命令実行直後PICがリセットする場合があります。 これは、PICの仕様によるものです。これを避ける方法についてはPICの データブックをご覧ください。 この命令はoption命令に展開されるので、メモリページの切り替えはしません。
<内部動作>
movlw lite
option

mov option,fr
<内部動作>
movf fr,0
option

mov option,W
<内部動作>
option

mov !port_fr,#lite
PICの入出力レジスタの設定を行います。 port_frにポート位置(RA,RB,RC等)を設定します。頭の!マークを忘れないでください。 定数liteのビットが0の時出力ポート、1の時入力ポートとなります。 通常リセット直後は全ビット1(全て入力ポート)に設定されています。 だいたいのプログラムはリセットの後にこの命令を書いてI/Oピンの設定 を行う場合が多いようです。 この命令はtris命令に展開されるので、メモリページの切り替えはしません。
<内部動作>
movlw lite
tris port_fr

mov !port_fr,fr
<内部動作>
movf fr,0
tris port_fr

mov !port_fr,W
<内部動作>
tris port_fr

mov W,#lite
<内部動作>
movlw lite

mov W,fr
<内部動作>
movf fr,0

mov W,/fr
<内部動作>
comf fr,0

mov W,fr-W
<内部動作>
subwf fr,0

mov W,++fr
<内部動作>
incf fr,0

mov W,--fr
<内部動作>
decf fr,0

mov W,<
<内部動作>
rlf fr,0

mov W,>>fr
<内部動作>
rrf fr,0

mov W,<>fr
<内部動作>
swapf fr,0

movb bit1,bit2 (MOVe Bit field)
ビット単位の移動を行います。bit1,bit2で指定された以外のビットは影響を受けません。 bit2に入力ポートのビットを指定した場合は注意が必要です。
内部でビットテストを2回行っているため、1回目のテストと2回目のテストで入力ポート の値に変化があると正常な動作が期待できません。 また、bit1に1をセットするケースと0にクリアするケースではI/Oピンの変化する 時間が異なります。
<内部動作>
btfss bit2
bcf bit1
btfsc bit2
bsf bit1

movb bit1,/bit2
<内部動作>
btfsc bit2
bcf bit1
btfss bit2
bsf bit1

movsz W,++fr
<内部動作>
incfsz fr,0

movsz W,--fr
<内部動作>
decfsz fr,0

neg fr
ファイルレジスタfrの2の補数をとります。
内部では全ビット反転してから、1を加算します。 (なぜこうやるかは、コンピュータ数学を勉強しましょう)
<内部動作>
comf fr,1
incf fr,1

not fr
全ビットを反転します。それだけです。Zフラグが変化します。 パソコン等のCPUではこのニーモニックの方が一般的なような気がします>マイクロチップさん
<内部動作>
comf fr,1

not W
全ビットを反転します。それだけです。Zフラグが変化します。 PICのインストラクションではWレジスタとのnot(に相当する)命令がない 為、FFhとXORを取ります。
<内部動作>
xorlw 0ffh

or fr,#lite
<内部動作>
movlw lite
iorwf fr,1

or fr1,fr2
<内部動作>
movf fr2,0
iorwf fr1,1

or fr,W
<内部動作>
iorwf fr,1

or W,#lite
<内部動作>
iorlw lite

or W,fr
<内部動作>
iorwf fr,0

ret (RETurn from subroutine)
サブルーチンからリターンする命令です。return命令と基本的に同じですが、 この命令はretlw 0の命令に展開されるため、Wレジスタに0になりますので注意してください。
<内部動作>
retlw 0

retw lite1[,lite2,lite3...]
マイクロチップのインストラクションretlwと基本的に同じです。 違うのはオペランドを2個以上置くことが可能です。(retlw はオペランドを1つしか置けない)
複数のオペランドは指定した個数のretlw命令に展開されます。(内部動作を参照) 又、文字列を指定した場合は1文字づつASCIIコードで展開されます。 <例> retw 0,1,2,3,4,5 retw 'Sample' ; 文字列指定 retw 'S','a','m','p','l','e' ; 上の書き方と同じ
<内部動作>
retlw lite1
retlw lite2
retlw lite3
....

rl fr
<内部動作>
rlf fr,1

rr fr
<内部動作>
rrf fr,1

sb bit
<内部動作>
btfss bit

sc
<内部動作>
btfss 3,0

setb bit (SET bit field)
bitで指定されたビット位置を1にセットします。 この命令はマイクロチップのbsfインストラクションとまったく同じ動作です。 実行クロックは1サイクルです。
<内部動作>
bsf bit

skip
<内部動作>
btfss 4,7

snb bit
<内部動作>
btfsc bit

snc
<内部動作>
btfsc 3,0

snz
<内部動作>
btfsc 3,2

stc (SeT Carry flag)
Cフラグを1にセットします。実行クロックは1サイクルです。
<内部動作>
bsf 3,0

stz (SeT Zero flag)
Zフラグを1にセットします。実行クロックは1サイクルです。
<内部動作>
bsf 3,2

sub fr,#lite
<内部動作>
movlw lite
subwf fr,1

sub fr1,fr2
<内部動作>
movf fr2,0
subwf fr1,1

sub fr,W
<内部動作>
subwf fr,1

subb fr,bit
<内部動作>
btfss bit
decf fr,1

swap fr
<内部動作>
swapf fr,1

sz
<内部動作>
btfss 3,2

test fr
ファイルレジスタfrの値をテスト(0かそれ以外かチェック)します frが0のときZフラグが1にセット、frが0以外の時Zフラグが0にクリアされます。 この命令はファイルレジスタがクリアされているかチェックする命令です。
<内部動作>
movf fr,1

test W
Wレジスタが0かどうかテストします。結果はZフラグに反映します。
<内部動作>
iorlw 0

xor fr,#lite
<内部動作>
movlw lite
xorwf fr,1

xor fr1,fr2
<内部動作>
movf fr2,0
xorwf fr1,1

xor fr,W
<内部動作>
xorwf fr,1

xor W,#lite
<内部動作>
xorlw lite

xor W,fr
<内部動作>
xorwf fr,0