2010-11-02 4 views
0

Возможно ли в MIPS изменить во время исполнения значение метки или создать метку с определенным значением?MIPS assembly - модификация значения метки

Я спрашиваю об этом, потому что, используя инструкцию lw $a0, label($s0), я хочу увеличивать значение метки +4 при каждом цикле, указывая новый адрес памяти массива. Я знаю, что могу сделать lw $a0, label+4($s0), но новое значение метки не будет сохранено.

Любые советы?

ответ

3

№ В 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 

Это может быть целесообразно использовать Адду, если s0 всегда будет неотрицательным.

EDIT: вы не можете изменить значение метки. Это единственный псевдоним для местоположения в памяти. В текстовом разделе это псевдоним для позиции следующей инструкции. В разделе данных это псевдоним для местоположения в памяти следующего пространства.

+0

Благодарим за редактирование и информацию, не пропустите голосования в 1 час. Голосов пока нет :) – Carlos

+0

Нет проблем. Какой имитатор MIPS вы используете? Если вы используете MARS, вы можете видеть адреса памяти, используемые для замены ярлыков (в расширенной сборке) и почему они должны быть константой (иначе ассемблер не знал бы, что делать). – Kizaru

+0

yep amateur using MARS, нормально плохое начало делать это :) – Carlos

0

Я действительно думаю, что ответ должен быть уточнен и возвращен к «Да». Я думаю, что между «адресом» и «значением» возникла недоразумение и смешение.

В настоящее время у меня есть массив, в который я хочу перейти, чтобы сделать вид пузыря. Чтобы узнать, когда остановиться, мне нужно значение индекса для сравнения с длительностью массива, которая является постоянной.

Я создал 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 x 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.

Надеюсь, это поможет.

+0

Вы говорите о значении, хранящемся по адресу помеченной памяти, который вы можете, конечно, изменить с помощью 'sw'. Но значение ** ** - это его адрес, и об этом спрашивает ОП. Обратите внимание, что синтаксис сборки GNU работает именно так: '.equ A, 50' устанавливает значение символа равным 50, а' A: 'устанавливает значение символа на адрес. (Связано [сборка - как умножать/делить константу на другую константу в сборке?] (Https://stackoverflow.com/questions/46869106/assembly-how-to-multiply-divide-a-constant-by-another- константа в сборке/46870205 # 46870205) –

+0

(TL: DR: OP не понял, что вы перебираете массивы, увеличивая регистр, а не метку). –

+0

Этикетки представляют собой чисто время сборки и время ссылки вещи, а не вещи времени выполнения. Они дают нам символический способ получить адреса памяти, встроенные в байты машинного кода, без учета байтов вручную. (А также позволить ассемблеру сделать заметку для компоновщика, чтобы заполнить правильный адрес после ссылки несколько файлов '.o' вместе.) –