#assembly #mips #memory-address
#сборка #mips #память-адрес
Вопрос:
У меня есть этот код:
.data
array: .word 13, 11, 5, 9, 0, -3
size: .word 6
.text
Main:
la $a0, array
lw $a1, size
jal PrintIntArray
j Exit
# $a0 - array, $a1 - size
PrintIntArray:
addi $sp, $sp, -12
li $t0, 0
sw $t0, 0($sp) # i
sw $a0, 4($sp) # array
sw $a1, 8($sp) # size
li $a0, '['
li $v0, 11
syscall
lw $t1, 8($sp) # size
ble $t1, $0, EmptyArray
PrintLoop:
lw $t1, 8($sp) # size
lw $t0, 0($sp) # i
bge $t0, $t1, PrintLoopEnd
lw $t0, 0($sp) # i
lw $t2, 4($sp) # array
add $t2, $t2, $t0
lw $a0, 0($t2) # <====== RUNTIME EXCEPTION AT THIS LINE !!!
li $v0, 1
syscall
li $a0, ','
li $v0, 11
syscall
lw $t0, 0($sp) # i
add $t0, $t0, 1
sw $t0, 0($sp)
j PrintLoop
PrintLoopEnd:
EmptyArray:
li $a0, ']'
li $v0, 11
syscall
jr $ra
Exit:
Строка, отмеченная мной, создает следующее исключение во время выполнения:
Ошибка в строке 37 util.asm: исключение во время выполнения при 0x00400060: адрес выборки не выровнен по границе слова 0x10010001
Что я сделал не так? Полагаю, я допустил какую-то ошибку при загрузке / сохранении адреса.
Ответ №1:
Вам нужно умножить i на размер элемента массива, затем добавить его к базовому адресу массива, чтобы вычислить адрес i-го элемента. Обратите внимание, что, если размер элемента равен 4 байтам, это умножение может быть легко выполнено сдвигом влево на два бита.
Ответ №2:
Вы пытаетесь выполнить невыровненную 32-разрядную загрузку, которая не разрешена в (универсальных) архитектурах MIPS. Когда i
равно единице, вы пытаетесь загрузить адрес формы 0x10010000 (array) 1 (i)
. Попробуйте умножить t0 (i) на 4, прежде чем добавлять его в t2 (массив)
Ответ №3:
Вместо того, чтобы увеличивать i
на 1, попробуйте следующее
add $t0, $t0, 4
вместо
add $t0, $t0, 1
Это добавит к вашему индексу размер 32-разрядного целого числа в байтах. MIPS требует, чтобы 4-байтовые значения сохранялись и загружались с адресов, кратных 4 байтам. (т.е. с двумя нулевыми битами младшего порядка.)