2017-02-10 14 views
1

я пытаюсь перевести этот простой фрагмент C в MIPS:Невозможно выяснить ошибку MIPS в MARS: Ошибка в: недопустимое значение счетчика программы: 0x00000000 Перейти: выполнение прекращается с ошибками

int leaf_example(int g, int h, int i, int j) { 
    int f; 
    f = (g + h) - (i + j); 
    return f; 
} 

Это мой MIPS код:

.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 

Однако, когда я компилирую и попытка запуска этого, он дает мне эту ошибку:

«Ошибка: недопустимое значение счетчика программы: 0x00000000

Перейти: выполнение завершено с ошибками. "

Я вообще не понимаю эту ошибку. Может кто-то указать мне верное направление?

+1

Вы храните 12 байт в стеке, но только выделенное пространство для 8. – Jester

+0

'точка PC' к следующей инструкции в памяти для выполнения. Если он указывает на '0x0000', ваш' PC' указывает куда-то не так. Возможно, вы переопределили его где-нибудь в своем коде. –

+0

@Jester Что значит? Он начинается с 0, и у меня есть три элемента: 0, 4 и 8. Должен ли мой код 'addi $ sp, $ sp, -12 ...' вместо этого? –

ответ

0

На самом деле вам не нужно сохранять и восстанавливать $t0,$t1 Так как если вызывающая функция не использует эти регистры, то усилия по их сохранению и восстановлению теряют силу . Чтобы избежать этих отходов, MIPS делит регистры на сохраненные и незапечатанные категории. Сохраненные регистры включают $s0 – $s7 (отсюда их имя сохранено). Непризнанные регистры включают $t0 – $t9 (отсюда их название, временное). Функция должна сохранить и восстановить любой из сохраненных регистров, который он хочет использовать, но он может свободно изменять регистры, не поддерживаемые.

.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 

Улучшенная версия.

.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 
1

Кажется, что MARS инициализируется регистр $ra в 0x00000000 и используя jr $ra, программа подскочила до 0x00000000, который считается недействительными.

Я думаю, вы должны написать код, который вызывает функцию leaf (а затем выйдите через system call № 10) после main:, чтобы проверить вашу функцию.

+0

Хорошо ... как бы я это сделал? –

+0

'jal leaf' правый? –