2013.11.25
前へ
次へ
ホームページトップへ戻る

復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります

[第515回]


●PICのテーブル参照 retlw命令とPCLATHレジスタ(3)

前回からの続きです。
私はPIC16Fでのテーブル参照で使う addwf PCL,f命令がプログラムカウンタの下位8ビットしか変えられないものと勝手に納得してしまっていました。
そのためにテーブルは256バイト以内に押さえ、かつテーブルの開始アドレスをわざわざORGを使って下位8ビットが00になるように設定したのですが、それがかえって裏目に出てしまい、意味不明の暴走という結果を招いてしまいました。

実はaddwf PCL,f命令がプログラムカウンタの下位8ビットしか変えられないというのは、私の勝手な思い込みに過ぎませんでした。
前回もお見せした下の図なのですが、これをよーく見ますと意味深なことが書いてあります。


[出典]Microchip Technology Inc. PIC16F887 Data Sheet

この図の説明として、右肩のところに
Instruction with PCL as Destination
と書いてあります。
むむむ。
そーいうことだったのか。

PCLを目的レジスタとする命令、つまりPCLを変化させる命令では、図のようにPCL(プログラムカウンタの下位8ビット)を変化させると同時にプログラムカウンタの上位5ビットには必ずPCLATHの値が入れられる、という動作をする、ということがわかりました。

それでやっと納得できました。
PCLATHレジスタの値はresetによって00になります。
そしてここが肝心なところなのですが、PCLATHの値はユーザーがプログラムによって書き換えない限り変化しません。
そして、それはPCLを書き換える命令と、CALL、GOTO命令以外には影響を与えません。
がしかし、ここでCALL、GOTOについての説明をするとちょっと話がややこしくなってしまいますのでそれは後で説明することにします。
ここではもしプログラム、テーブルデータがページ0(アドレス000〜7FF)の範囲に収まっているならば、CALL、GOTOについて気にする必要は無いと考えてください。

さてそういうことが理解できますと、前回書きましたように、テーブルをアドレス0300に置いて、
   org 0300
table
   addwf PCL,f
   retlw XX
   …
としたときに、ただ
CALL table
を実行すると、PCLATHの初期値は00なので、もしもwレジスタの値が08だったとすると、
addwf PCL,f
の実行の結果プログラムアドレスは0308ではなくて0008になってしまい暴走してしまうことがわかってきます。
そしてこれを正しく実行するためには、CALL tableの実行前に(直前である必要はありません)、PCLATHに03をセットしておけばよいこともわかります。

そうなってくると、テーブルの途中でアドレス上位に桁上がりが発生するような場合でも、事前にPCLATHの値を+1しておくことで対応できそうだと思えてきます。
がしかし、桁上がりの問題はそれほど簡単ではなさそうです。
というのは、
addwf PCL,f
の実行の結果、桁上がりが生じてキャリーフラグが立ったとしても、そのタイミングでは遅いからです。
それよりも前にPCLATHの値を+1しておかなければならないという、鶏が先か玉子が先かという悩ましい問題を解決しなければなりません。
これには事前にtableのアドレスを取得して、それにwレジスタの値を加算して桁上がりが生じるかどうかを確認するという、やや本末転倒な作業をすることになりかねません。
そう考えますとやはりテーブルはORGを使ってさきほどの例のように下位アドレスが00になるようなアドレスに置くのが最も安全な策ではないかと思います。

本日は時間がなくなってしまいました。
次回は実際のサンプルプログラムをお見せすることにいたします。

ワンボードマイコンでCP/Mを![第515回]
2013.11.25upload

前へ
次へ
ホームページトップへ戻る