[PIC]HI-TECH Cのサンプルプログラムを逆アセンブルしてみる

前に作りかけたPic16f84のCPUシミュレータですが、暇が出来たので開発を再開させます。

ずいぶん久しぶりなので、何をやってたかを思い出すのを兼ねて、動作確認用サンプルのhexファイルを作る事にします。


今回の対象はHI-TECH Cのコンパイラをインストールしたときに一緒に入っているサンプルPGです。
ファイルは、標準インストールだと以下の辺りに入ってます。

C:\Program Files\HI-TECH Software\PICC\9.83\samples\misc\led.c



このプログラムはLEDの点滅プログラムで、コードは以下の通りのシンプルなものです。
“Freely distributable.”らしいので、ソースを全文転記します。

#include    <htc.h>
 
/*
 *  Demo program
 *
 *  Flashes LEDs on Port B, responds to switch press
 *  on RA1. Usable on PICDEM board.
 *
 *  Copyright (C)1997 HI-TECH Software.
 *  Freely distributable.
 */
#define BUTTON  RC1 //bit 1 of PORTC
 
main(void)
{
    unsigned char   i, j;
 
    TRISB = 0;      /* all bits output */
    j = 0;
    for(;;) {
        PORTB = 0x00;       /* turn all on */
        for(i = 100 ; --i ;)
            continue;
        PORTB = ~j;     /* output value of j */
        for(i = 100 ; --i ;)
            continue;
        if(BUTTON == 0)     /* if switch pressed, increment */
            j++;
    }
}



コメントにも有りますが、このプログラムでは以下の処理をしています。

 1. ポートBのLEDを点滅させます。
 2. RA1のスイッチを押すと点滅する値が変わります。



…なはずですが、このコード、コメントはRA1にボタンが繋がっている書かれてるのに、#defineがRC1になってます。16F84AにPORTCは無いので、これはRA1に書き換えておきます。

#define BUTTON  RC1 //bit 1 of PORTC




#define BUTTON  RA1 //bit 1 of PORTA





で、MPLABでプロジェクトを作ってコンパイルした結果は以下の通りです。

---  C:\home\project\pic\16F84A_Example_LED\16F84A_Example_LED.as  -------------------------------
1:                 opt subtitle "HI-TECH Software Omniscient Code Generator (Lite mode) build 10920"
2:                 
3:                 opt pagewidth 120
4:                 
5:                  opt lm
6:                 
7:                  processor   16F84A
8:                 clrc macro
9:                  bcf 3,0
10:                 endm
11:                clrz macro
12:                 bcf 3,2
13:                 endm
14:                setc macro
15:                 bsf 3,0
16:                 endm
17:                setz macro
18:                 bsf 3,2
19:                 endm
20:                skipc    macro
21:                 btfss   3,0
22:                 endm
23:                skipz    macro
24:                 btfss   3,2
25:                 endm
26:                skipnc   macro
27:                 btfsc   3,0
28:                 endm
29:                skipnz   macro
30:                 btfsc   3,2
31:                 endm
32:                indf equ 0
33:                indf0    equ 0
34:                pc   equ 2
35:                pcl  equ 2
36:                status   equ 3
37:                fsr  equ 4
38:                fsr0 equ 4
39:                c    equ 1
40:                z    equ 0
41:                pclath   equ 10
42:                 FNROOT  _main
43:                 global  _EEADR
44:                psect    maintext,global,class=CODE,delta=2
45:                global __pmaintext
46:                __pmaintext:
47:                _EEADR   set 9
48:                 global  _EEDATA
49:                _EEDATA  set 8
50:                 global  _PORTB
51:                _PORTB   set 6
52:                 global  _CARRY
53:                _CARRY   set 24
54:                 global  _GIE
55:                _GIE set 95
56:                 global  _RA1
57:                _RA1 set 41
58:                 global  _EECON1
59:                _EECON1  set 136
60:                 global  _EECON2
61:                _EECON2  set 137
62:                 global  _TRISB
63:                _TRISB   set 134
64:                 global  _RD
65:                _RD  set 1088
66:                 global  _WR
67:                _WR  set 1089
68:                 global  _WREN
69:                _WREN    set 1090
70:                 file    "16F84A_Example_LED.as"
71:                 line    #
72:                psect cinit,class=CODE,delta=2
73:                global start_initialization
74:                start_initialization:
75:                
76:                psect cinit,class=CODE,delta=2
77:                global end_of_initialization
78:                
79:                ;End of C runtime variable initialization code
80:                
81:                end_of_initialization:
82:                clrf status
   3D1    0183     CLRF 0x3
83:                ljmp _main   ;jump to C main() function
   3D2    2BD3     GOTO 0x3d3
---  C:\home\project\pic\16F84A_Example_LED\led.c  -----------------------------------------------
1:                 #include <htc.h>
2:                 
3:                 /*
4:                  *   Demo program
5:                  *
6:                  *   Flashes LEDs on Port B, responds to switch press
7:                  *   on RA1. Usable on PICDEM board.
8:                  *
9:                  *   Copyright (C)1997 HI-TECH Software.
10:                 *   Freely distributable.
11:                 */
12:                
13:                //#define BUTTON RC1 //bit 1 of PORTC
14:                #define BUTTON   RA1 //bit 1 of PORTA
15:                
16:                main(void)
17:                {
18:                 unsigned char   i, j;
19:                
20:                 TRISB = 0;      /* all bits output */
   3D3    1683     BSF 0x3, 0x5
   3D4    0186     CLRF 0x6
21:                 j = 0;
   3D5    1283     BCF 0x3, 0x5
   3D6    018D     CLRF 0xd
22:                 for(;;) {
23:                     PORTB = 0x00;       /* turn all on */
   3D7    0186     CLRF 0x6
24:                     for(i = 100 ; --i ;)
   3D8    3064     MOVLW 0x64
   3D9    008C     MOVWF 0xc
   3DA    080C     MOVF 0xc, W
   3DB    008E     MOVWF 0xe
   3DC    2BDF     GOTO 0x3df
   3DF    3001     MOVLW 0x1
   3E0    028E     SUBWF 0xe, F
   3E1    1D03     BTFSS 0x3, 0x2
   3E2    2BE4     GOTO 0x3e4
   3E3    2BE5     GOTO 0x3e5
   3E4    2BDF     GOTO 0x3df
   3E5    2BE6     GOTO 0x3e6
25:                         continue;
   3DD    2BDF     GOTO 0x3df
   3DE    2BDF     GOTO 0x3df
26:                     PORTB = ~j;     /* output value of j */
   3E6    090D     COMF 0xd, W
   3E7    0086     MOVWF 0x6
27:                     for(i = 100 ; --i ;)
   3E8    3064     MOVLW 0x64
   3E9    008C     MOVWF 0xc
   3EA    080C     MOVF 0xc, W
   3EB    008E     MOVWF 0xe
   3EC    2BEF     GOTO 0x3ef
   3EF    3001     MOVLW 0x1
   3F0    028E     SUBWF 0xe, F
   3F1    1D03     BTFSS 0x3, 0x2
   3F2    2BF4     GOTO 0x3f4
   3F3    2BF5     GOTO 0x3f5
   3F4    2BEF     GOTO 0x3ef
28:                         continue;
   3ED    2BEF     GOTO 0x3ef
   3EE    2BEF     GOTO 0x3ef
29:                     if(BUTTON == 0)     /* if switch pressed, increment */
   3F5    1885     BTFSC 0x5, 0x1
   3F6    2BF8     GOTO 0x3f8
   3F7    2BF9     GOTO 0x3f9
   3F8    2BD7     GOTO 0x3d7
30:                         j++;
   3F9    3001     MOVLW 0x1
   3FA    008C     MOVWF 0xc
   3FB    080C     MOVF 0xc, W
   3FC    078D     ADDWF 0xd, F
   3FD    2BD7     GOTO 0x3d7
31:                 }
   3FE    2BD7     GOTO 0x3d7
32:                }
   3FF    2800     GOTO 0




実際のプログラムはmainだけですが、スタートアップルーチンが有るのでかなり長くなってます。
最初のスタートアップの*.asファイルは83行も有りますが、ほとんどはアセンブラ(MPASM.exe)に対する指示で、実際のコードは以下の2つだけです。

82:                clrf status
   3D1    0183     CLRF 0x3
83:                ljmp _main   ;jump to C main() function
   3D2    2BD3     GOTO 0x3d3



MPLABでプログラムメモリを見ると、最初の命令は”GOTO 0x03d1″なのでこのコードに飛んでいます。


で、スタートアップルーチンはステータスレジスタをクリア(CLRF 0x3)した後、main()にジャンプするだけ(GOTO 0x3d3)なので、理解するのは楽勝です。



プログラム本体は、Program Memoryウィンドウ上でもぎりぎり1画面に表示できるレベルでした。
HI-TECH Cはコードを0x03FFの上位番地側に詰めて配置するようです。



hexファイルは、たったこれだけです。

:02000000D12B02
:1007A2008301D32B8316860183128D018601643067
:1007B2008C000C088E00DF2BDF2BDF2B01308E022A
:1007C200031DE42BE52BDF2BE62B0D09860064309D
:1007D2008C000C088E00EF2BEF2BEF2B01308E02DA
:1007E200031DF42BF52BEF2B8518F82BF92BD72BA8
:0E07F20001308C000C088D07D72BD72B002868
:00000001FF




このhexファイルを、以前作った逆アセンブラで処理させてみます。


…驚くべき事に、ちゃんと処理されったっぽいです。


前回作ったシミュレータは、GOTOとADD命令だけしか解釈できなかったので、次回はこのコードを動かせるところまでがんばってみます。

関連記事

コメントを残す

メールアドレスが公開されることはありません。