PICの命令とアセンブリ言語

  1. PICの命令の特徴

     
    1. 命令の構成とバンクメモリ

       PICはRISC(reduced instruction set Computer)型のシンプルな命令を高速に実行する方式を採用しています。すべての命令は14bitとなっています。

      • 演算系

        演算系の命令は、6ビットの命令コード部、1ビットの演算結果を指定する目的部、そして演算の対象となるアドレス部は7bitになっています。命令で直接指定できるメモリは128バイトに限定されます。dは結果を記録する場所を指定し、0のときW、1のときfで指定した番地のレジスタファイルとなります。

         
        0 0 c c c c d f f f f f f f
      • ビット処理系

        ビット処理命令は、3ビットのビット部bで、対象番地fのビットを直接操作することができます。これは制御系のコンピュータで多用されるビット処理を意識した命令です。

        0 1 c c b b b f f f f f f f
      • 定数系

        定数命令は、8ビットの定数kを直接指定して演算することができます。

        1 1 c c c c k k k k k k k k
      • ジャンプ系命令

         ジャンプ命令はコード部3ビット、ジャンプ先を示すアドレスが11ビットです。

        1 0 c a a a a a a a a a a a
    2. スキップ命令

       命令のビット長の制限から、ジャンプ命令ではジャンプの条件が指定できません。そこで、バイト命令にスキップ機能を追加し、条件付ジャンプを実現しました。スキップ機能は、指定した条件が満たされた場合、次の命令をスキップし、「次の次」の命令を実行する機能です。条件が満足されない場合、次の命令を実行します。

       スキップ命令を利用すると、繰返しプログラムは次のようになります。

      LOOP  繰返し先頭
          繰返し
          条件付スキップ
          GOTO LOOP
      NEXT    繰返し終了

       条件付スキップ命令で、条件が満たされないと、次の GOTO LOOP 命令で、LOOP 番地に戻ります。条件が満たされると、GOTO LOOP 命令をスキップするため、繰返しが終了します。

    3. 入出力命令

       PICでは命令で、直接外部ピンの値を読み込んだり、値の設定ができます。これは SFR(Special Function Register)を利用します。SFR は 0..1F 番地のメモリとして配置されており、
       例えば、SFRの PORTB は6H番地に割り付けられており、PORTB 番地を読み書きすることで、RB7..RB0 の8本のポートB端子(ピン RB7..RB0)の値を呼んだり、値を設定できます。
       また、 86H番地の TRISB レジスタに値を設定することで、PORTB の端子の入力と出力を設定できます。

      PORTA(5H)
      RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0
      PORTB(6H)
      RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
      RISA(85H)
      RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0
      TRISB(86H)
      RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
    4. メモリバンク

      プログラムで直接指定できる番地は7ビットです。データメモリを増やすためバンク方式を採用し、予め上位の2ビットを指定して128バイト単位のメモリ(これをバンクといいます)を切替えて使用する方法が採用されています。
       ジャンプ系で指定できる番地のサイズが2047に限定されます。そこで、命令も2047命令を1バンクとして4バンクを切替えて使用する方式になっています。

  2. 記号命令と機能

    1. 記号命令と記法

       ここでは、命令はその機能を示すコード部とその対象を記号で表現します。

       MOVLW  0F9H

      で、MOVLWが命令の記号、0F9Hは命令で利用されるデータです。こn場合、0F)Hは16進の定数です。この記法をアセンブリ命令(記号命令)といいます。

    2. 命令の対象の記法

       ここでは、以下の記号を利用します。
       c:1バイトの定数
       a:11ビットのプログラムメモリの番地
       f:7ビットのレジスタファイルの番地
       b:ビットを示す定数(0..7)
       d:Wまたはfを示す1ビットの定数、演算結果を記録するレジスタを指定します。

    3. 定数(リテラル)命令

       演算はW(Working)レジスタが仲介をします。定数系の命令は1バイトの定数cを指定して、Wレジスタへの値を設定したり、Wに定数を演算してWに戻します。
       MOVLW c
      命令は 定数c をWレジスタに送ります。演算MOVの次のLWが(Literal、Work)を意味します。
       ADDLW(SUBLW) はWレジスタにkを加える(減算する)
       ANDLW, IORLW, XORLW
      は、AND(論理積)、IOR(論理和)、XOR(排他的論理和)を行います。

      MOVLW k 定数kをWに送ります
      ADDLW k kにWを加える
      SUBLW k kからWを引く
      ANDLW k kにWをANDする
      IOR k kにWをORする
      XOR k kにWをXORする

      例 MOVLW  0F9H ;Wレジスタの値を0F9Hとする

    4. 単一オペランド系

       このグループは、主にf(データメモリ)のみを対象に処理を行う命令です。
      移動を行う命令は
       MOVWF f と、//WをFに
       MOVF f,d   //fをWに
      の2タイプになります。

        INCF f 、
        DECF f
      はfの内容に1を加えたり(INC)減らし(DEC)ます。

       CLRF f、 
      はfの値を0にします(clear)。
       CLEW
      はWレジスタをクリアします。

       COMF f,d
      は、fの各ビットを反転(complement)し、結果をWまたはfに返します。

       RLF f,d 、RRF f,d
      は、fを1ビット左(RLF:Rotate Right)または右(RRF:Rotate Right)に回転し、結果をWまたはfに返します。

      fの第bビットを設定する命令があります。fの第bビットを1(BSF)、0(BCF)にします。
       BSF f,b
       BCF f,b

      MOVWF f Wをfに移動
      MOVF f,W fをWに移動 Z
      CLRF f fを0にする Z
      CLRW Wを0にする
      COMF f,[W|F] fの2の補数をWまたはfに送る
      DECF f,[W|F] fを1減らしWまたはfに送る Z
      INCF f,[W|F] fを1増しWまたはfに送る
      RLF f fをキャリCを含めて左回転 C
      RRF f fをキャリCを含めて右回転 C
      SWAPF f fの左右4ビットを入れ替え
      BSF f,b fのbビットを1にする
      BCF f,b fのbビットを0にする
    5. バイト処理系

      WF系の命令は、f番地のメモリとWを演算し結果をWまたはfに返します。
       ADDWF f,d
      はWにf番地を加え、dが1のときWに、0のときfに結果を返します。fが特殊レジスタ(SFR)を指定する場合、SFRの機能に応じた動作をします。
       演算はLW系と同じで、SUBWF,以外に
       ANDLW, IORLW, XORLW
      が利用できます。

      ADDWF f,[W|F] Wにfを加算し結果をWまたはfに送る C,DC,Z
      SUBWF f,[W|F] f からWを引き結果をWまたはfに送る C,DC,Z
      ANDWF f,[W|F] fにWをANDし結果をWまたはfに送る Z
      IORWF f,[W|F] fにWをORし結果をWまたはfに送る Z
      XORWF f,[W|F] fにWをXORし結果をWまたはfに送る Z

      例 MOVWF CNT1 ;Wの値をレジスタファイルのCNT1に保存する。
         ここで、CNT1はレジスタファイルのラベルです。
        MOVF VALUE,W ;レジスタファイルのVALUEをWに保存する

    6. 制御系

       計算機は原則として次の番地にある命令を実行します。この実行順序を変更するのが制御系の命令です。

       GOTO a

      は、次に実行する番地を a に変更します。a は11ビットですから、0〜2047の番地を指定することができます。ただし、GOTO命令は実行の条件を指定できません。条件付でジャンプするには、条件付スキップ機能をもった命令とGOTO命令を組み合わせます。条件付スキップは、指定条件が満たされている場合、次の命令を飛び越して、「次の次」の命令を実行する機能です。スキップする命令がジャンプ命令であれば、ジャンプ命令をスキップできます。

       DECFSZ f,F ;fを一つ減らし、0になれば次の命令をスキップ
       GOTO LOOP ;LOOPへジャンプ

      スキップ機能を持つ命令は他に、して0ならスキップする命令です。
       INCFSZ f,d

      「指定ビット」の値でスキップする命令があります。

       BTFSC f,b
       BTFSS f,b
      BTFSC は、fの指定ビットが0のとき次の命令をスキップします。また、BTFSSは指定ビットが1のときスキップします。

      サブルーティン呼び出しは

       CALL a
      命令を利用します。これは、C言語の「関数呼び出し」と「戻り」に対応する機能です。CALL a ではa番地を呼び出しますが、このとき、次の番地を戻り番地として「スタック」に記憶しておきます。
       サブルーティンからの戻りには
       RETURN
      命令を利用します。また、
       RETLW k
      では、定数kをWレジスタに保存して戻る命令です。

      戻り番地が保存されるスタックは8レベルですから、連続した呼び出しは8回までに限定されます。

      DECFSZ f fを1減らし、0になったら次の命令をスキップする
      INCFSZ f fを1増し、0になったら次の命令をスキップする
      BTFSC f,b fのbビットが0なら次の命令をスキップ
      BTFSS f,b fのbビットが1なら次の命令をスキップ
      GOTO a a番地にジャンプする
      CALL a a番地のサブルーチンを呼ぶ
      RETURN 戻る
      RETLW k 定数をWにセットし戻る
      RETFIE 割り込みから戻る
      CLRWDT Watch Dog Timer をクリアする PD,TO
      SLEEP スリープモードに入る PD,TO
      NOP 何もしない(時間調整用)
    7. 命令一覧

      こちらに命令一覧表をまとめます。A4 用紙1枚に印刷可能です。

  3. アセンブリ言語

    1. アセンブリ言語とは

      アセンブリ言語は記号言語とも呼ばれます。プログラムを構成する「命令」を、対応する記号で表現したものがアセンブリプログラムになります。

    2. 命令の記号

       命令の種類を記号で表現します。例えば、定数をワークレジスタに記憶する命令は
        MOVLW
      と指定します。

    3. 番地の記号表現

       特定の番地を記号で代表し、プログラムではその記号で番地を指定します。たとえば、
        goto a
      命令はa番地にジャンプする命令です。これを

      LOOP   MOVLW  23h
      ...
      CALL LOOP

      と表現します。LOOP が記号番地で MOVLW の命令が記録され番地を代表します。
       CALL  LOOP
      はこの番地を参照します。LOOPの値は MOVLW 命令が記録されている番地となります。

    4. 値の記号化

       次のように、名前に値を設定しておきます。
       val  EQU  値
      EQUは宣言命令または擬似命令と呼ばれ、実行する命令ではありません。

      DATA   EQU    20h
             MOVFW  DATA

      このプログラムは、DATAの値を20hとし、MOVFWのこの値を参照し、20h番地の レジスタファイルの値をWレジスタに移します。記号化することで、DATAの値を変更するとき、EQUの値を変更するだけで、DATAを参照しているすべての命令の値を変更することができます。

    5. その他の宣言命令

      #include <ファイル名> ;この位置からファイルの内容を展開します。
      ORG 番地   ;プログラムの開始番地を指定します。
      END       ;プログラムの終了を指定します。
      DT  <値1>,<値2>,..,<値4>  ; RETLW命令で、戻り値を設定します。
      DE   <値1>,<値2>,..,<値4> ;EEPROMにデータを定義します。

    6. アセンブリプログラムの例を示します。これは30番地から6バイトに0から5の値を順に記憶するプログラムです。

              org         0 ;プログラムの先頭
                
              movlw       0x6
              movwf       count ;count<-6 
              movlw       0x30
              movwf       FSR ;メモリ先頭<-30
              movlw       0
              movwf       val
      NEXT    movf        val,w
              movwf       INDF ;FSRの番地にWを書き込む
              incf        FSR,f
              incf        val,f
              decfsz      count ;countを減らし
              goto        NEXT ;0でなければNEXTへ戻る
      loop    goto        loop ;終了
      
              end