int sum(int a[], int n)
{
int i, s;
s = 0;
for (i = 0; i < n; i++)
sum += a[i];
return s;
}
Oplossing
Toelichting bij commentaar:
- C heeft geen boolean variabelen.
In plaats daarvan worden integer variabelen gebruikt,
waarbij 0 gelijk staat aan false en
alle andere waarden gelijk staan aan true.
Als x een integer variabele is, dan betekent
!x ``NOT x''.
Dus als x gelijk is aan 0, dan is !x true.
Als x een andere waarde heeft, dan is !x false (0).
- Als x een variabele is, dan is &x het adres
van x. &a[0] is dus het adres van a[0]
wat weer gelijk is aan het startadres van de array a.
sum: add $v0,$zero,$zero # s = 0
add $t0,$zero,$zero # i = 0
sum_L: slt $t1,$t0,$a1 # $t1 = (i < n)
beq $t1,$zero,sum_exit # if (!$t1) goto sum_exit
add $t1,$t0,$t0
add $t1,$t1,$t1 # $t1 = 4*i
add $t1,$t1,$a0 # $t1 = &a[i]
lw $t1,0($t1) # $t1 = a[i]
add $v0,$v0,$t1 # s += a[i]
addi $t0,$t0,1 # i++
j sum_L # goto sum_L
sum_exit:
jr $ra # return
We kunnen dit optimaliseren zodat er nog maar 1 spronginstructie
per iteratie nodig is:
sum: add $v0,$zero,$zero # s = 0
add $t0,$zero,$zero # i = 0
slt $t1,$t0,$a1 # $t1 = (i < n)
beq $t1,$zero,sum_exit # if (!$t1) goto sum_exit
sum_L: add $t1,$t0,$t0
add $t1,$t1,$t1 # $t1 = 4*i
add $t1,$t1,$a0 # $t1 = &a[i]
lw $t1,0($t1) # $t1 = a[i]
add $v0,$v0,$t1 # s += a[i]
addi $t0,$t0,1 # i++
slt $t1,$t0,$a1 # $t1 = (i < n)
bne $t1,$zero,sum_L # if ($t1) goto sum_L
sum_exit:
jr $ra # return
Dit kan nog verder geoptimaliseerd worden; de adressen van a[i] en a[i+1]
verschillen met 4. Dus men kan het adres van a[i] in elke loop iteratie
bijhouden en hoeft dan niet meer iedere keer 4*i te berekenen en het
startadres van a erbij optellen.
$a0 hoeft niet gesaved te worden, want dat is de verantwoordelijkheid
van de caller.
sum: add $v0,$zero,$zero # s = 0
add $t0,$zero,$zero # i = 0
slt $t1,$t0,$a1 # $t1 = (i < n)
beq $t1,$zero,sum_exit # if (!$t1) goto sum_exit
sum_L: lw $t1,0($a0) # $t1 = a[i]
add $v0,$v0,$t1 # s += a[i]
addi $t0,$t0,1 # i++
addi $a0,$a0,4 # $a0 = &a[i]
slt $t1,$t0,$a1 # $t1 = (i < n)
bne $t1,$zero,sum_L # if ($t1) goto sum_L
sum_exit:
jr $ra # return