UMEHOSHI ITA TOP PAGE

変数(auto,global)を制御変数にした繰り返しで、hello文字列をUSBに出力する

レジスタを使った繰り返しの参照先

下記内容で実際にアセンブル可能なページへのリンクは、このページの最後にあります。
ます、UMEHOSHI ITA基板で使っている制御チップのPIC32MX270F256B用アセンブリ(MIPS32系)概要を示します

C言語(xc32-gcc)のauto変数とグローバル変数で生成されるアセンブリの違いを調べる

上記のhello出力を3回繰り返す処理の例で比較します。
(左の列がauto変数、右の列がグローバル変数を制御変数とした繰り返しです。)
01
02
03
04
05
06
07
08
09
10
11
12
#include <xc.h>	// test.c
#include "common.h"

__attribute__((address( 0x80005000 ))) void test_main (void);
void test_main(){
	int count=0xffff;//ローカルのauto変数
	for(count = 0; count < 3; count++){
		__asm__ ("NOP");
		_send_string("hello\r\n");//USBへ文字列送出
		__asm__ ("NOP");
	}
}
#include <xc.h>	// test.c
#include "common.h"

__attribute__((address( 0x80005000 ))) void test_main (void);
int count=0xffff;// グローバル変数
void test_main(){
	for(count = 0; count < 3; count++){
		__asm__ ("NOP");
		_send_string("hello\r\n");//USBへ文字列送出
		__asm__ ("NOP");
	}
}
上記のローカル変数利用のアセンブリコードが下記コード 上記のグローバル変数利用のアセンブリコードが下記コード
左右とも、繰り返しを制御の構造は同じで、制御変数を初期化後10行目で、繰り返し判定用のL2に移動している。
繰り返し判定で繰り返しを続ける場合は、30行目で戻るジャンプを行っている。
左右の違いは制御変数の取り扱いで、左のautoローカル変数はスタック、右のグローバル変数はメモリを利用している。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
45
46
47
48
49
50
51
52
53
54


Disassembly of section _0620b64064179b48:

80005000 :
80005000:	27bdffe0 	addiu	sp,sp,-32
80005004:	afbf001c 	sw	ra,28(sp)
80005008:	afbe0018 	sw	s8,24(sp)
8000500c:	03a0f021 	move	s8,sp
80005010:	3402ffff 	li	v0,0xffff
80005014:	afc20010 	sw	v0,16(s8)
80005018:	08001413 	j	8000504c <.L2>
8000501c:	afc00010 	sw	zero,16(s8)
80005020:	00000000 	nop
80005024:	3c02a000 	lui	v0,0xa000
80005028:	344241a4 	ori	v0,v0,0x41a4
8000502c:	8c420000 	lw	v0,0(v0)
80005030:	3c038000 	lui	v1,0x8000
80005034:	0040f809 	jalr	v0
80005038:	24645080 	addiu	a0,v1,20608
8000503c:	00000000 	nop
80005040:	8fc20010 	lw	v0,16(s8)
80005044:	24420001 	addiu	v0,v0,1
80005048:	afc20010 	sw	v0,16(s8)



8000504c <.L2>:
8000504c:	8fc20010 	lw	v0,16(s8)
80005050:	28420003 	slti	v0,v0,3

80005054:	1440fff2 	bnez	v0,80005020 
80005058:	00000000 	nop


8000505c:	03c0e821 	move	sp,s8
80005060:	8fbf001c 	lw	ra,28(sp)
80005064:	8fbe0018 	lw	s8,24(sp)
80005068:	03e00008 	jr	ra
8000506c:	27bd0020 	addiu	sp,sp,32














80005080 <.LC0>:
80005080:	6c6c6568 	0x6c6c6568
80005084:	000a0d6f 	0xa0d6f
Disassembly of section _0626364064186f27:

80005000 :
80005000:	27bdffe8 	addiu	sp,sp,-24
80005004:	afbf0014 	sw	ra,20(sp)
80005008:	afbe0010 	sw	s8,16(sp)
8000500c:	03a0f021 	move	s8,sp
80005010:	3c028001 	lui	v0,0x8001

80005014:	08001414 	j	80005050 <.L2>
80005018:	ac408000 	sw	zero,-32768(v0)
8000501c:	00000000 	nop
80005020:	3c02a000 	lui	v0,0xa000
80005024:	344241a4 	ori	v0,v0,0x41a4
80005028:	8c420000 	lw	v0,0(v0)
8000502c:	3c038000 	lui	v1,0x8000
80005030:	0040f809 	jalr	v0
80005034:	24645098 	addiu	a0,v1,20632
80005038:	00000000 	nop
8000503c:	3c028001 	lui	v0,0x8001
80005040:	8c428000 	lw	v0,-32768(v0)
80005044:	24430001 	addiu	v1,v0,1
80005048:	3c028001 	lui	v0,0x8001
8000504c:	ac438000 	sw	v1,-32768(v0)

80005050 <.L2>:
80005050:	3c028001 	lui	v0,0x8001
80005054:	8c428000 	lw	v0,-32768(v0)
80005058:	28420003 	slti	v0,v0,3
8000505c:	1440ffef 	bnez	v0,8000501c 
80005060:	00000000 	nop

80005064:	03c0e821 	move	sp,s8
80005068:	8fbf0014 	lw	ra,20(sp)
8000506c:	8fbe0010 	lw	s8,16(sp)
80005070:	03e00008 	jr	ra
80005074:	27bd0018 	addiu	sp,sp,24

Disassembly of section .dinit:

80005078 <.dinit>:
80005078:	80008000 	lb	zero,-32768(zero)
8000507c:	00000004 	sllv	zero,zero,zero
80005080:	00000001 	movf	zero,zero,$fcc0
80005084:	0000ffff 	0xffff
80005088:	00000000 	nop
8000508c:	22222222 	addi	v0,s1,8738
80005090:	22222222 	addi	v0,s1,8738
80005094:	22222222 	addi	v0,s1,8738

Disassembly of section .rodata:

80005098 <.LC0>:
80005098:	6c6c6568 	0x6c6c6568
8000509c:	000a0d6f 	0xa0d6f
スタックにローカル変数を作るため、
04行のスタックの確保量が右より多く-32にしている。
そして、s8にspを設定してs8を介して
スタック上の変数をアクセスしている。

それにより、autoのcount変数は、
 16(s8)でアクセスしてる。

09行の「sw v0,16(s8)」がcount=v0です。(v0に0xffff)
11行の「sw zero,16(s8)」がcount=0です。

"hello"文字列は、.LC0のラベル位置にあり、
そのアドレス:80005080番地の設定を、上位と下位に分けて、
16行で、v0の上位16bitに0x8000を設定し、
18行で、v0の下位6bitに0x5080(10進の20608)を
addiuによる加算で設定しすることで、
v0に80005080番地を設定しています。
(この手法は、右上も同じです)

下記の実行可能のリンクでは、このhello文字列のラベル名を
.L_STR_HELLOにしています。


ローカル変数を使わないため、スタック確保は
 04行の-24で、左より少ない。

11行の「sw	zero,-32768(v0)」がcount=0です。
v0に0x8001が記憶されているので、
アクセス対象番地は、(0x8001<<16)+(-32768)で得られ、
0x80008000番地のcount変数をゼロにしています。

そして0x80008000は、[UMEHOSI ITA]において、
ユーザプログラムのRAM領域になっています。

count=00xffffの初期設定は、
利用されていないためか、その初期化コードは、
存在していませんでした。

.dinitのセクションが存在しています。
.dinitは、スタートアップ コードによって
RAM 変数にコピーされる初期値を保持するために、
存在するものですが、[UMEHOSHI ITA]で使う
ユーザプログラムでは、使っていません。
(余計な、コードになっています。)

下記の実行可能のリンクでは、
.dinitの生成をしません。
また、count=00xffffの初期化は、
次のように行わせています。
      .section   SEC01,address(0x80008000),code
count:
      .word      0x0000ffff

上記コードを実際にアッセンブルするリンク 上記コードを実際にアッセンブルするリンク