Reputation: 984
I am trying to translate this simple C fragment into MIPS:
int leaf_example(int g, int h, int i, int j) {
int f;
f = (g + h) - (i + j);
return f;
}
This is my MIPS code:
.text
main:
leaf:
addi $sp, $sp, -8 #adjust stack to make room for 3 items
sw $t1, 8($sp) #save register $t1 for use in memory location 8
sw $t0, 4($sp) #save register $t0 for use in memory location 4
sw $s0, 0($sp) #save register $s0 for use in memory location 0
add $t0, $a0, $a1 #register $t0 contains $a0 + $a1
add $t1, $a2, $a3 #register $t1 contains $a2 + $a3
sub $s0, $t0, $t1 #$t0 = $t0 - $t1 -> $t0 = ($a0 + $a1) - ($a2 + $a3)
add $v0, $s0, $zero #copy $s0 to return register $v0
#Before returning, we restore three original values of registers we pushed onto stack by popping them
lw $s0, 0($sp) #restore register $s0 for caller
lw $t0, 4($sp) #restore register $t0 for caller
lw $t1, 8($sp) #restore register $t1 for caller
addi $sp, $sp, 8 #adjust stack to delete 3 items
jr $ra #jump back to calling routine
However, when I compile and attempt to run this, it gives me this error:
"Error in : invalid program counter value: 0x00000000
Go: execution terminated with errors."
I do not understand this error at all. Can anyone point me in the right direction?
Upvotes: 1
Views: 4052
Reputation: 846
Actually you don't need to save and restore $t0,$t1
Since if the calling function does not use those registers, the
effort to save and restore them is wasted. To avoid this waste, MIPS divides
registers into preserved and nonpreserved categories. The preserved registers include $s0 – $s7
(hence their name, saved). The nonpreserved registers
include $t0 – $t9
(hence their name, temporary). A function must save and
restore any of the preserved registers that it wishes to use, but it can change
the nonpreserved registers freely.
.text
main:
addi $a0,$0,1 #argument 0 = 1
addi $a1,$0,2 #argument 1 = 2
addi $a2,$0,3 #argument 2 = 3
addi $a3,$0,4 #argument 3 = 4
jal leaf # call function leaf
add $s0,$v0,$zero # return value
li $v0,10
syscall
leaf:
addi $sp, $sp, -12 #adjust stack to make room for 3 items
sw $s0, 8($sp) #save register $t1 for use in memory location 8
sw $t0, 4($sp) #save register $t0 for use in memory location 4
sw $t1, 0($sp) #save register $s0 for use in memory location 0
add $t0, $a0, $a1 #register $t0 contains $a0 + $a1
add $t1, $a2, $a3 #register $t1 contains $a2 + $a3
sub $s0, $t0, $t1 #$t0 = $t0 - $t1 -> $t0 = ($a0 + $a1) - ($a2 + $a3)
add $v0, $s0, $zero #copy $s0 to return register $v0
#Before returning, we restore three original values of registers we pushed onto stack by popping them
lw $t1, 0($sp) #restore register $s0 for caller
lw $t0, 4($sp) #restore register $t0 for caller
lw $s0, 8($sp) #restore register $t1 for caller
addi $sp, $sp, 12 #adjust stack to delete 3 items
jr $ra #jump back to calling routine
The improved version.
.text
main:
addi $a0,$0,2 #argument 0 = 2
addi $a1,$0,3 #argument 1 = 3
addi $a2,$0,4 #argument 2 = 4
addi $a3,$0,5 #argument 3 = 5
jal leaf # call function leaf
add $s0,$v0,$zero # return value
li $v0,10
syscall
leaf:
addi $sp, $sp, -4 #adjust stack to make room for 3 items
sw $s0, 0($sp) #save register $t1 for use in memory location 8
add $t0, $a0, $a1 #register $t0 contains $a0 + $a1
add $t1, $a2, $a3 #register $t1 contains $a2 + $a3
sub $s0, $t0, $t1 #$t0 = $t0 - $t1 -> $t0 = ($a0 + $a1) - ($a2 + $a3)
add $v0, $s0, $0 #copy $s0 to return register $v0
#Before returning, we restore three
#original values of registers we pushed
#onto stack by popping them
lw $s0, 0($sp) #restore register $t1 for caller
addi $sp, $sp, 4 #adjust stack to delete 3 items
jr $ra #jump back to calling routine
Upvotes: 0
Reputation: 75062
It seems that MARS initialized the register $ra
to 0x00000000
and using jr $ra
, the program jumped to 0x00000000
, which is considered as invalid.
I guess you should write some code that calls the function leaf
(and then exit via system call no. 10) after main:
to test your function.
Upvotes: 1