Jonathan Dewein
Jonathan Dewein

Reputation: 984

Unable to figure out MIPS error in MARS: Error in : invalid program counter value: 0x00000000 Go: execution terminated with errors

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

Answers (2)

Adam
Adam

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

MikeCAT
MikeCAT

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

Related Questions