#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. Да, я не могу поверить, что я этого не заметил. Такие вещи, чувак…