2010年9月8日作成 2010年9月8日更新

PIC の C言語でループの書き方によるコードサイズの違い

MPLAB に付属している HI-TECH C for PIC10/12/16 V9.71a (PICC)でループがどんな感じにアセンブラへ展開されるかを比べてみた。


参考に、まずアセンブラで直接書いた場合


	movlw	8
	movwf	count		; count=8
loop:	bcf	PORTA,RA0	; RA0=0
	decfsz	count,1		; count=count-1 して、
				; 結果がゼロなら次の命令をスキップ
	goto	loop

5ワード!



	for(count=0; count<8; count++) RA0=0;

   046    1003     BCF 0x3, 0
   047    3000     MOVLW 0
   048    1803     BTFSC 0x3, 0
   049    3001     MOVLW 0x1
   04A    1283     BCF 0x3, 0x5
   04B    009A     MOVWF 0x1a
   04C    3008     MOVLW 0x8
   04D    021A     SUBWF 0x1a, W
   04E    1C03     BTFSS 0x3, 0
   04F    2851     GOTO 0x51
   050    2852     GOTO 0x52
   051    2853     GOTO 0x53
   052    285E     GOTO 0x5e
   053    1005     BCF 0x5, 0
   054    3001     MOVLW 0x1
   055    0097     MOVWF 0x17
   056    0817     MOVF 0x17, W
   057    079A     ADDWF 0x1a, F
   058    3008     MOVLW 0x8
   059    021A     SUBWF 0x1a, W
   05A    1C03     BTFSS 0x3, 0
   05B    285D     GOTO 0x5d
   05C    285E     GOTO 0x5e
   05D    2853     GOTO 0x53

24ワード

自分が何も考えず書くとこうなる



	for(count=0; count==7; count++) RA0=0;

   05E    1003     BCF 0x3, 0
   05F    3000     MOVLW 0
   060    1803     BTFSC 0x3, 0
   061    3001     MOVLW 0x1
   062    009A     MOVWF 0x1a
   063    081A     MOVF 0x1a, W
   064    3A07     XORLW 0x7
   065    1903     BTFSC 0x3, 0x2
   066    2868     GOTO 0x68
   067    2869     GOTO 0x69
   068    286A     GOTO 0x6a
   069    2875     GOTO 0x75
   06A    1005     BCF 0x5, 0
   06B    3001     MOVLW 0x1
   06C    0097     MOVWF 0x17
   06D    0817     MOVF 0x17, W
   06E    079A     ADDWF 0x1a, F
   06F    081A     MOVF 0x1a, W
   070    3A07     XORLW 0x7
   071    1903     BTFSC 0x3, 0x2
   072    2874     GOTO 0x74
   073    2875     GOTO 0x75
   074    286A     GOTO 0x6a

23ワード



	for(count=8; count==0; count--) RA0=0;

   075    3008     MOVLW 0x8
   076    0097     MOVWF 0x17
   077    0817     MOVF 0x17, W
   078    009A     MOVWF 0x1a
   079    081A     MOVF 0x1a, W
   07A    1D03     BTFSS 0x3, 0x2
   07B    287D     GOTO 0x7d
   07C    287E     GOTO 0x7e
   07D    2885     GOTO 0x85
   07E    1005     BCF 0x5, 0
   07F    3001     MOVLW 0x1
   080    029A     SUBWF 0x1a, F
   081    081A     MOVF 0x1a, W
   082    1D03     BTFSS 0x3, 0x2
   083    2885     GOTO 0x85
   084    287E     GOTO 0x7e

16ワード

「ゼロになるまで」という条件にするとだいぶ縮んだ。



	count=0;
	while(count<8)
	{
		RA0=0;
		count++;
	}

   085    1003     BCF 0x3, 0
   086    3000     MOVLW 0
   087    1803     BTFSC 0x3, 0
   088    3001     MOVLW 0x1
   089    009A     MOVWF 0x1a
   08A    2890     GOTO 0x90
   090    3008     MOVLW 0x8
   091    021A     SUBWF 0x1a, W
   092    1C03     BTFSS 0x3, 0
   093    2895     GOTO 0x95
   094    2896     GOTO 0x96
   095    288B     GOTO 0x8b
   08B    1005     BCF 0x5, 0
   08C    3001     MOVLW 0x1
   08D    0097     MOVWF 0x17
   08E    0817     MOVF 0x17, W
   08F    079A     ADDWF 0x1a, F

17ワード

for 文の代わりに、while 文を使ったほうがコンパクトになるみたい。



	count=8;
	while(1)
	{
		RA0=0;
		if(--count==0)break;
	}

   096    3007     MOVLW 0x8
   097    0097     MOVWF 0x17
   098    0817     MOVF 0x17, W
   099    009A     MOVWF 0x1a
   0A2    289A     GOTO 0x9a
   09A    1005     BCF 0x5, 0
   09B    3001     MOVLW 0x1
   09C    029A     SUBWF 0x1a, F
   09D    1D03     BTFSS 0x3, 0x2
   09E    28A0     GOTO 0xa0
   09F    28A1     GOTO 0xa1
   0A0    28A2     GOTO 0xa2
   0A1    28A3     GOTO 0xa3

13ワード

Cで書いた場合、これが一番サイズが小さくなる感じ


PIC には decfsz のように、レジスタをデクリメントして結果がゼロかどうかを調べる命令があるんだけれども、コンパイラはそれを使ってくれないみたい。


webmaster@kyoutan.jpn.org

('A`)