Перебор массива в MIPS

#assembly #mips

#сборка #mips

Вопрос:

У меня есть массив в MIPS, и я пытаюсь выполнить итерацию по нему.

Этот код работает, когда я хочу получить значение определенной ячейки массива, но он выдает время выполнения, address out of range 0x10565554 когда я пытаюсь перебрать его.

 .data
boardState: .word 
        0, 0, 0, 0, 0, 0, 0, 0,        
        0, 0, 0, 0, 0, 0, 0, 0,        
        1, 2, 3, 4, 5, 6, 7, 8,        
        9, 10, 11, 12, 13, 14, 15, 16, 
        0, 0, 0, 0, 0, 0, 0, 0,        
        0, 0, 0, 0, 0, 0, 0, 0,        
        0, 0, 0, 0, 0, 0, 0, 0,        
        0, 0, 0, 0, 0, 0, 0, 0,        
        17, 18, 19, 20, 21, 22, 23, 24,
        25, 26, 27, 28, 29, 30, 31, 32,
        0, 0, 0, 0, 0, 0, 0, 0,        
        0, 0, 0, 0, 0, 0, 0, 0         
.text

main:
    la $t3, boardState
    li $t2, 0
    li $t4, 63
    jal loop

loop:
    add $t2, $t2, $t2
    add $t2, $t2, $t2 #quadruple index
    add $t1, $t2, $t3 #add index/offset to array address

    lw $a0, 0($t1) #load word into $a0 ***this is where it throws the error***
    li $v0, 1      #load syscall for printing integer
    syscall

    beq $t2, $t4, exit #branches to a syscall 10 if array length is reached
    addi $t2, $t2, 1   #else iterates and jumps back to loop beginning
    j loop
  

У меня есть ветка под этим названием single , которая не использует цикл, но, как я уже сказал, она использует тот же точный код для поиска индекса массива и печатает его с помощью syscall и работает отлично.

Я где-то нашел фрагмент кода, который использовался sll для увеличения индекса, но я действительно не знаю, как использовать sll . Я придерживаюсь этого кода, потому что он работает в единственном экземпляре.

Комментарии:

1. То, как вы обновляете $t1 сейчас, означает, что вы будете накапливать все индексы по мере продвижения. Либо измените add $t1, $t2, $t3 , чтобы использовать другой регистр в качестве места назначения, а затем использовать этот регистр в качестве адреса для lw , либо удалите первые три строки цикла и поместите addi $t1, $t1, 4 прямо перед j loop .

Ответ №1:

Выполните это в отладчике одним шагом, и вы увидите ошибку.

На языке C это примерно то, что делает код:

 for ( int t2 = 0; t2 != 63; t2   ) {
    t2 *= 4;
    ...boardState[t2]...;
}
  

Итак, переменные управления циклом увеличиваются в четыре раза, а также увеличиваются.

Таким образом, $t2 принимает следующие значения: 0, 0, 1, 4, 5, 20, 21, 84, 85, 340, 341, 1364, 1365, 5460, 5461, …

Поскольку в тесте условия выхода из цикла используется равенство (= 63) , а управляющая переменная цикла не увеличивается строго на 1, это не соответствует условию выхода из цикла, и в конечном итоге произойдет сбой при попытке загрузки из памяти с неверным адресом с использованием очень, очень большого индекса.

Но если вы пройдете по коду всего за 2 итерации, вы сможете обнаружить проблему.

Комментарии:

1. Да, я не могу поверить, что я этого не заметил. Такие вещи, чувак…