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

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

[第534回]


●テーブル参照

とうとう大晦日になってしまいました。
このところずっとテーマ違いのままきています。
年が明けましたら少しずつ、テーマ別に再整理したいと思っているのですが、果たしてその時間がありますかどうか…。

前回からの続きです。
やっとテーブル参照の説明にたどりつきました。
下は前回もお見せしたメインプログラムのリストですが、ここでは前回も説明しましたようにテーブルを参照しています。

loop
        clrf cntr
        clrf udmk
loop1
        movlw 0a;=10
        movwf limit
loop2
        bsf PORTE,2
        movf cntr,w
        call Htable
        movwf t1Hdata
        movf cntr,w
        call Ltable
        movwf t1Ldata
        call t25ms
        bcf PORTE,2
        call t25ms
        btfsc udmk,0
        goto downcount
        incf cntr,f
        decfsz limit,f
        goto loop2
;set downcount
        incf udmk,f
        decf cntr,f
        goto loop1
downcount
        decf cntr,f
        decfsz limit,f
        goto loop2
        goto loop
;


テーブル参照の仕組みです。
wレジスタにキーになる値をいれてテーブルの先頭アドレスをCALLすると、キーによって選択された結果の値がwレジスタに入ってリターンしてきます。
下はメインプログラムでCALLする2つのテーブルです。

;
        org 400
;
Htable
    addwf PCL,f
    retlw 0d8
    retlw 0dc
    retlw 0e0
    retlw 0e4
    retlw 0e8
    retlw 0ec
    retlw 0f0
    retlw 0f4
    retlw 0f8
    retlw 0fc
;
Ltable
    addwf PCL,f
    retlw 0f0
    retlw 0d8
    retlw 0c0
    retlw 0a8
    retlw 90
    retlw 78
    retlw 60
    retlw 48
    retlw 30
    retlw 18
;
     end


テーブル参照はコード変換と考えることができます。
Htableはキーが00のときにD8Hを、01のときにDCHを、02のときにE0Hを、というようにそれぞれ値が選択されます。
その仕組みはこうです。
PCLはプログラムカウンタの下位8ビットです。
addwf PCL,fを実行する時点でプログラムカウンタにはその次のアドレスが入っています。
その値にwレジスタの値を加算したものがPCLの新しい値になります。
この命令の実行によってプログラムカウンタが更新されますから、その結果は次にそのプログラムカウンタが示すアドレスにジャンプして、そこにある命令が実行されることになります。
addwf PCL,fの次に並んでいる命令はretlw命令ばかりです。
retlw nn は、nnをwレジスタに入れてリターンする命令です。
この仕組みによって、wレジスタの値が示す位置に置かれたretlw命令の値がwレジスタに入れられて戻ってきます。

さて。
長々とここまで説明をしてきました理由は、上のリストに書かれた ORG 400 にありました。
HtableとLtableの置かれているアドレスは400H番地台です。
ところがPCLは8ビットですから、上位ビットの値である’4’はaddwf PCL,fでは計算できません。
ですから、普通にこういうプログラムを書くとプログラムが期待した通りには実行されずに大抵は暴走してしまいます。
そのような場合でも正しくテーブル参照が実行できるように用意されているのがPCLATHレジスタです。
PCLATHレジスタについては[第513回][第515回]で説明をしました。
あらかじめPCLATHにテーブルのあるアドレスの上位5ビットを入れておくことで、テーブル参照が正しく実行されるようになります(PICのプログラムカウンタは13ビットです)。
しかしこのPCLATHについては、ネット上ではかなり誤解されているところもあるようです。
そこで今回のサンプルプログラムでPCLATHについて本当のところを確認してみたのです。

やれやれ。
やっと、結論までたどりつけました。
ネット上ではPCLATHが文字通りプログラムカウンタの上位カウンタそのものである、と解釈して混乱してしまっている方などのページも見受けられます。
正確に言いますとPCLATHはプログラムカウンタ(の上位5ビット)ではありません。
言うならばプログラムカウンタの仮レジスタのようなものです。
PCLATHは通常の命令では全く参照されません。
ではどういうときにPCLATHが使われるかと言いますと、addwf PCL,f のようにプログラムカウンタの値を変更するような命令が実行されたときに、PCLATHが使われます。
PCLが変更されると同時に、PCLATHの(下位5ビットの)値がプログラムカウンタの上位5ビットに入れられます。
この働きによって、メインプログラムから離れたアドレスにあるテーブルでも参照することができるようになります。

実はPCLATHが参照される命令が他にもあります。
それはgotoとcallです。
そのことをテーブル参照と合わせて説明しているページもあります。
そのように説明をしながら、筆者自身が誤解をしてしまっているのではないかと思われるサイトなどもあるようです。
PCLATHについてよく理解しないまま、gotoやcallでも使われるなどという説明をしますと、それならテーブルと同じように上位アドレスが異なっているアドレスに置いたサブルーチンや割込みプログラムをcallするときにもPCLATHに値を設定しなくてはいけないのではないか、などという誤解をしてしまいます。
実はそのような混乱を避ける目的で、PCLATHについての説明図を引用しましたときに、わざとgoto、callに関する部分をカットしてお見せしました([第514回])。

本当はこういう図になっています。


[出典]Microchip Technology Inc. PIC16F882〜887Data Sheet

図の中でPCHとあるのがプログラムカウンタの上位5ビットです。
PCHはプログラムで直接書き換えることはできません。
図の上側がテーブル参照に関係する部分です。
instruction with PCL as Destination という説明がついています。
意訳すると「PCLを書き換える命令」です。
図の下がgoto、callに関する部分です。

PIC16Fのプログラムカウンタは13ビットです。
ということはアクセスできる範囲は00000 00000000〜11111 11111111です。
つまり0000〜1FFFの範囲です。
バイトで表現すると8KBです。
ところでこれも[第514回]で少し書いたことですが、PIC16Fのgotoやcallのマシン語コードのオペランドは11バイトしかありません。
ということは2KBの範囲しか直接アクセスできないことになります。
そこでプログラムメモリを2KBずつのバンクに分割しているのです([第514回]参照)。
そして上の図の下半分の説明は、PCLATHを使った、バンクを越えてアクセスする仕組みを説明している図です。

その図のように、gotoやcallが実行されるときには、PCLATHの2ビットの値がプログラムカウンタの上位2ビットに入れられるのですが、そのような仕組みに気を使わなければならないのは、プログラムが2KBを越えるような大きなプログラムを書くときだけですから、普通はこのことは考えなくてもよいと思います。
しかし、もしも2KBを越えるような大きいプログラムを書くときには、図からわかりますように、PCLを書き換える命令で使われるPCLATHの値と、goto、callで使われるPCLATHの値が2ビット重なっている点に十分注意する必要があります。

今回でちょうど終わるようにしたいと思っていたのですが、いろいろ書いておりますうちに、今回も時間切れになってしまいました。
この続きは次回に説明することにいたします。

今年一年拙文にお付き合いいただき有難うございました。
来年もよろしくお願いいたします。
皆様よいお年をお迎えください。

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

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