Сборка MIPS - изменение значения метки
Возможно ли в MIPS изменить во время выполнения значение метки или создать метку с определенным значением?
Я спрашиваю это, потому что при использовании инструкции lw $a0, label($s0)
я хочу увеличивать значение метки +4 каждый раз, когда мы выполняем цикл, указывая новый адрес памяти массива. Я знаю, что могу сделать lw $a0, label+4($s0)
но новое значение метки не будет сохранено.
Любой совет?
2 ответа
Нет. В MIPS вы должны иметь константу вне скобок при разыменовании (плохая формулировка). Если бы можно было изменить значение метки, то оно больше не было бы постоянным. Чтобы обойти это, вы могли бы вместо этого сделать что-то вроде
la $t1, label #t1 holds address of label
add $t1, $t1, $s0 #t1 now holds address of label + s0 offset
lw $a0, 0($t1) #load word from t1's location
addi $t1, $t1, 4 #t1 was incremented by 4 bytes now
lw $a0, 0($t1) #load the next word
Может быть целесообразно использовать addu, если s0 всегда будет неотрицательным.
РЕДАКТИРОВАТЬ: Вы не можете изменить значение метки. Это исключительно псевдоним для места в памяти. В текстовом разделе это псевдоним позиции следующей инструкции. В разделе данных это псевдоним для местоположения в памяти следующего пространства.
Я думаю, что ответ должен быть уточнен и дан ответ "Да". Я думаю, что произошло недопонимание и путаница между "адресом" и "ценностью".
В настоящее время у меня есть массив, по которому я хочу перемещаться, чтобы выполнять пузырьковую сортировку. Чтобы узнать, когда остановиться, мне нужно, чтобы значение индекса сравнивалось с постоянной величиной массива.
Я создал arrayLength
ярлык, и, увидев "нет" в этом ответе, я застрял на 4 часа, пытаясь изменить значение arrayLength
со значением от пользователя, прежде чем я запомнил слово магазина sw
,
Технически, да, вы не можете изменить базовый адрес массива, но вы можете прочитать следующий адрес, который следует.
Вот что вы можете сделать, чтобы получить длину массива для итерации по массиву с целым числом чтения:
li $v0, 5
syscall
.data
.word
.assign 2
arrayLength: 0
.text
sw $v0, arrayLength
lw $t0, arrayLength
С этой точки зрения, arrayLength
определяется пользователем, берется из $v0
, Путин arrayLength
затем хранится в $t0
от arrayLength
и может использоваться для сравнения итераций по массиву.
Другими словами, чтобы ответить на ваш вопрос, значение 0 в arrayLength
был перезаписан (для нашего примера, скажем, 10). Так что да, вы можете перезаписывать этикетки весь день. Что вы не можете сделать, это изменить адрес этого ярлыка.
Насколько мне известно, после создания метки она присваивается адресу, и следующие адреса распределяются в зависимости от того, как вы ее идентифицируете (.byte
, .half
, .word
, так далее.). Оттуда, если нет какого-либо способа удалить метку и воссоздать ее, вы не сможете изменить адрес. Это вызвало бы много проблем с управлением памятью и было бы очень неэффективным и сложным без причины.
Теперь продолжим. Как примечание, если вы не знали, вы можете предварительно определить массив с .space [number]
, Я думаю, что каждое значение по умолчанию 32 бита, так что 4 байта (слово). Так что, если вы хотите, скажем, 5 слов (слов), вы бы сделали 5 х 4, так .space 20
и вы можете хранить 5 слов в массиве.
В этом случае мы теперь предполагаем array
уже создан и заполнен из нашего arrayLength
из 10
и мы печатаем значение в каждом индексе следующим образом:
add $t1, $zero, $zero #index value 0, our base address index
loop:
li $v0, 1
lw $a0, array($t1)
syscall
addi $t1, $t1, 4 #increase the address index by 4 (each index is 4 bytes long)
addi $t3, 1, $zero #increase the index identifier by 1
blt $t3, arrayLength, loop
#exit
Так адресный указатель ($t1
) является буквальным адресом местоположения. Каждый индекс, т. Е. Слово, имеет длину 4 байта (32 бита). Таким образом, наш $t3 является идентификатором, который говорит (например): "Эй, мы находимся в позиции индекса 2 из 10", но на самом деле мы находимся в позиции адреса array + 8
снаружи array + 40
,
Вы могли бы, вероятно, изменить идентификатор индекса и просто сделать $t3 значением arrayLength x 4
и делать blt $t1, $t3, loop
,
Надеюсь это поможет.