0

Is it possible in MIPS to change during execution the value of a label, or to create a label with certain value?

I ask this because when using the instruction lw $a0, label($s0) i want to increment the value of label +4 every time we loop, indicating the new memory address of the array. I am aware I can do lw $a0, label+4($s0) but the new value of label will not be stored.

Any advise?

Carlos
  • 5,405
  • 21
  • 68
  • 114

2 Answers2

5

No. In MIPS you must have a constant outside the parentheses when dereferencing (poor wording). If it were possible to change the value of the label, then it would no longer be constant. To get around this, you could instead do something like

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

It might be advisable to use addu if s0 will always be non-negative.

EDIT: You cannot change the value of a label. It is solely an alias for a location in memory. In the text section, it's an alias for the position of the following instruction. In the data section, it's an alias for the location in memory of the following space.

Kizaru
  • 2,443
  • 3
  • 24
  • 39
  • thanks for the edit and the info, ill up-vote in 1hr. No votes available yet :) – Carlos Nov 02 '10 at 23:10
  • No problem. What MIPS simulator are you using? If you're using MARS, you can see the memory addresses used to replace labels (in the expanded assembly) and why it must be a constant (otherwise the assembler wouldn't know what to do). – Kizaru Nov 02 '10 at 23:22
  • yep am using MARS, ok ill start doing that :) – Carlos Nov 03 '10 at 00:01
0

I do think the answer should be clarified and reanswered to "Yes". I think there was a miscommunication and a mix-up between "address" and "value".

I currently have an array that I want to navigate to do a bubble sort. In order to know when to stop, I need an index value to compare with an array length that is persistent.

I created the arrayLength label, and after seeing "no" on this answer, I was stuck for 4 hours trying to change the value of arrayLength with a value from the user before I remembered store word sw.

Technically, yes, you can't change the base address of an array, but you can read the next address that follows.

Here is what you can do to get an array length to iterate over an array with a read integer:

li $v0, 5
syscall

.data
.word
.assign 2
arrayLength: 0

.text
sw $v0, arrayLength
lw $t0, arrayLength

At this point, arrayLength, defined by the user, is taken from $v0, put in arrayLength, then stored in $t0 from arrayLength, and can be used to compare to iterate over the array.

In other words to answer your question, the value of 0 in arrayLength was overwritten (for our example, lets say 10). So yes, you can overwrite labels all day long. What you cannot do is modify the address of that label.

To my knowledge, once a label is created, it is assigned to an address and the following addresses are allocated depending on how you identify it (.byte, .half, .word, etc.). From there, unless there is some way to delete a label and re-create it, you cannot modify the address. That would cause a LOT of issues with memory management and be very inefficient and complex for no reason.


Now to continue. As a note, if you didn't know, you can predefine an array with .space [number]. I think each value is by default 32 bits, so 4 bytes (a word). So if you wanted, say 5 items(words), you would do 5 x 4, so .space 20 and you can store 5 words into the array.

In this case, we now assume array is already created and filled in from our arrayLength of 10 and we are printing the value at each index, as follows:

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

So address index ($t1) is the literal address location. Each index, i.e: word, is 4 bytes (32 bits) long. So our $t3 is an identifier to say (for example), "Hey, we are at index location 2 of 10," but in reality, we are in address location array + 8 out of array + 40.

You could probably chuck the index identifier and just make $t3 the value of arrayLength x 4 and do blt $t1, $t3, loop.

Hope this helps.

  • You're talking about the value stored at a labeled memory address, which you can of course modify with `sw`. But the value **of** a label is its address, and that's what the OP is asking about. Note that GNU assembly syntax does work exactly this way: `.equ A, 50` sets the value of the symbol to 50, while `A:` sets the value of the symbol to an address. (Related [Assembly - How to multiply/divide a constant by another constant in assembly?](https://stackoverflow.com/questions/46869106/assembly-how-to-multiply-divide-a-constant-by-another-constant-in-assembly/46870205#46870205). – Peter Cordes Mar 09 '18 at 08:32
  • (TL:DR: the OP hadn't figured out that you loop through arrays by incrementing the register, not the label). – Peter Cordes Mar 09 '18 at 08:34
  • Labels are purely assemble-time and link-time things, not runtime things. They give us a symbolic way to get memory addresses embedded into the machine-code bytes without counting bytes by hand. (And also to let the assembler make a note for the linker to fill in the right address after linking multiple `.o` files together). – Peter Cordes Mar 09 '18 at 08:37
  • And BTW, it's a good idea to think of a label as a zero-width reference to the start of something. The `.byte` or `.word` or whatever that you place after a label starts at the labeled address, but the label itself has no size. It's just a name for the *start* of whatever you put there, and it's up to you to use word loads on words or byte loads on `.asciiz` data, as appropriate. Assembly language has no types, memory is just bytes. – Peter Cordes Mar 09 '18 at 08:39
  • Okay, that makes sense. I'm just surprised that the address is called the value. It makes sense, but seems confusing. I just started to do MIPS a few weeks ago for my class and it's very interesting. – Dark Swordsman Mar 09 '18 at 08:50
  • Most people don't talk about the value *of* a label very much, but some assemblers let you reassign the value (address) of a label within the same source file. Normally people use terminology like "`arrayLength` is 2 at this point", talking about the value labeled by the label, not the address. Exactly like a global variable in C. (Not coincidentally, global variables compile to a label and a `.word` or whatever). But if you want to know how the assembler itself "thinks" about labels, i.e. how they work in asm syntax, the way I described it is right. Assembly doesn't have variables. – Peter Cordes Mar 09 '18 at 08:57