3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

コンパイラのコード生成: 配列(カウンター方式)

Posted at

はじめに

このテキストは「コンパイラのコード生成: 繰返し」の続きです。

C言語プログラム例

下記のC言語プログラム例を見ていきましょう。

int calc(int a[], int n) {
	int sum = 0;
	for(int i = 0; i < n; i++) {
		sum += a[i];
	}
	return sum;
}

RISC-Vのアセンブリコード

次のようにコンパイルします。

riscv64-unknown-elf-gcc -S -O0 -march=rv32i -mabi=ilp32 -o sample.s sample.c

得られた RISC-V のアセンブリコードは次の通りです。

	.file	"sample.c"
	.option nopic
	.text
	.align	2
	.globl	calc
	.type	calc, @function
calc:
	addi	sp,sp,-48
	sw	s0,44(sp)
	addi	s0,sp,48
	sw	a0,-36(s0)
	sw	a1,-40(s0)
	sw	zero,-20(s0)
	sw	zero,-24(s0)
	j	.L2
.L3:
	lw	a5,-24(s0)
	slli	a5,a5,2
	lw	a4,-36(s0)
	add	a5,a4,a5
	lw	a5,0(a5)
	lw	a4,-20(s0)
	add	a5,a4,a5
	sw	a5,-20(s0)
	lw	a5,-24(s0)
	addi	a5,a5,1
	sw	a5,-24(s0)
.L2:
	lw	a4,-24(s0)
	lw	a5,-40(s0)
	blt	a4,a5,.L3
	lw	a5,-20(s0)
	mv	a0,a5
	lw	s0,44(sp)
	addi	sp,sp,48
	jr	ra
	.size	calc, .-calc
	.ident	"GCC: (GNU) 8.2.0"

演習問題

レジスタマップとメモリマップを作成してみましょう。

コード生成: 配列の参照

配列を参照している部分は次の通りです。

	lw	a5,-24(s0)
	slli	a5,a5,2
	lw	a4,-36(s0)
	add	a5,a4,a5
	lw	a5,0(a5)

-24(s0)i に相当し,slli a5,a5,2 によって i を4倍にします。さらに -36(s0)a すなわち配列 a の先頭アドレスになりますので,add a5,a4,a5によって a + i * 4 すなわち a[i]のアドレスがレジスタa5に入ります。

あとは lw a5, 0(a5) によって参照するというわけです。

コード生成: 配列への書き込み

逆に書き込む場合は,配列の参照のコードの最後を sw (格納したい値を入れたレジスタ), 0(a5) という具合にストア命令に書き換えます。

ポインタを使った場合

下記のコードは,同じ実行結果になるコードですが,配列の代わりにポインタを用いています。

int calc(int *a, int n) {
	int sum = 0;
	for(int i = 0; i < n; i++) {
		sum += *a++;
	}
	return sum;
}

RISC-Vのアセンブリコード例 (ポインタを用いた場合)

	.file	"samplep.c"
	.option nopic
	.text
	.align	2
	.globl	calc
	.type	calc, @function
calc:
	addi	sp,sp,-48
	sw	s0,44(sp)
	addi	s0,sp,48
	sw	a0,-36(s0)
	sw	a1,-40(s0)
	sw	zero,-20(s0)
	sw	zero,-24(s0)
	j	.L2
.L3:
	lw	a5,-36(s0)
	addi	a4,a5,4
	sw	a4,-36(s0)
	lw	a5,0(a5)
	lw	a4,-20(s0)
	add	a5,a4,a5
	sw	a5,-20(s0)
	lw	a5,-24(s0)
	addi	a5,a5,1
	sw	a5,-24(s0)
.L2:
	lw	a4,-24(s0)
	lw	a5,-40(s0)
	blt	a4,a5,.L3
	lw	a5,-20(s0)
	mv	a0,a5
	lw	s0,44(sp)
	addi	sp,sp,48
	jr	ra
	.size	calc, .-calc
	.ident	"GCC: (GNU) 8.2.0"

違いがわかりますか? 配列版では,slli 命令がありますが,ポインタ版ではありません。

演習課題

配列版とポインタ版のロジックをよく見比べてみましょう。違いを説明してください。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?