コンピュータアーキテクチャI課題解答例(第7回)

2015.11.18
コンピュータアーキテクチャI 課題解答例 (第 7 回)
1. 講義ノート 4 の演習 7,演習 8 をやってください.
演習 7:
main 関数の変数 g,h,i,j,k はそれぞれ$s0, ..., $s4 に割り当てられているものとする.
#main 関数のコンパイル
main:
....
addi
addi
#s0, $zero, 1
#s1, $zero, 2
#g=1
#h=2
addi
addi
#s2, $zero, 3
#s3, $zero, 4
#i=3
#j=4
add
add
add
$a0, $s0, $zero
$a1, $s1, $zero
$a2, $s2, $zero
#g を引数レジスタにコピー
#h を引数レジスタにコピー
#i を引数レジスタにコピー
add
jal
$a3, $s3, $zero
func1
#j を引数レジスタにコピー
#func1 の呼び出し.このとき$ra に戻り
add
$s4, $v0, $zero
......
#アドレスがセットされることに注意
#戻り値 ($v0 にある) を k に代入
演習 8:
#define STACKSIZE 4096
int stack[STACKSIZE];
int stkp=-1;
として,
void push(int data);
/*data を stack に積む.*/
int pop();
/*stack トップのデータを返す.*/
の本体を書く.
void push(int data){
if(stkp<STACKSIZE-1) {
stack[++stkp]=data;
} else {
printf("Error process");
}}
int pop(){
if(stkp<0) {
printf("error process");
} else {
1
return stack[stkp--];
}}
2. 講義ノート 4 の演習 9 を考えてみてください.
演習 9:
func1:
addi
sw
sw
sw
$sp, $sp, -12
$t1, 8($sp)
#func1 のコンパイル
#stack 上に 3 語分の領域を確保
#$t1 をセーブ (中間結果の保存のために使用)
$t0, 4($sp)
$s0, 0($sp)
#$t0 をセーブ (中間結果の保存のために使用)
#$s0 をセーブ (f 用に$s0 を使うため)
#ここから関数本体のコンパイル
add
$t0, $a0, $a1
sub
$t1, $a2, $a3
sub
add
$s0, $t0, $t1
$v0, $s0, $zero
#レジスタの回復
lw
$s0, 0($sp)
lw
$t0, 4($sp)
#g+h
#i-j
#f=(g+h)-(i-j)
#戻り値を$v0 にセット
#$s0 を回復
#$t0 を回復
lw
$t1, 8($sp)
#$t1 を回復
#Stack pointer を呼び出し前の状態に戻す
addi $sp, $sp, 12
#リターン
jr
$ra
#$ra には戻りアドレスが入っている
2
3. 教科書の問題 2.18.4 から 2.18.6 を行え.
問題 2.18.4
a. lw から bne までが 100 回繰り返される.よって,5x100+1=501 命令実行される.
b. LOOP: lw から bne まで 50 回繰り返される.よって,6x50+1=301 命令実行される.
問題 2.18.5
a. i=100; do result+=MemArray[i]; while(--i>0);
b. int *p, *i;
i=&MemArray[100]; p=MemArray;
do {result+=p[0]; result+=p[1];
p=p+8;} while(i!=p);
言い訳:C のプログラムを書かなくなって久しいので、ひょっとすると文法違反をしているかも
しれません。間違いがあったら指摘してください。
問題 2.18.6
a.
addi
$t1, $s0, 400
LOOP: lw
add
addi
$s1, 0($s0)
$s2, $s2, $s1
$s0, $s0, 4
bne
$t1, $s0, LOOP
ループ内 1 命令削減
b.
addi
LOOP: lw
add
$t1, $s0, 400
$s1, 0($s0)
$s2, $s2, $s1
addi $s0, $s0, 4
bne
$t1, $s0, LOOP
ループ内 2 命令削減
3