Understanding Assembly MIPS .ALIGN and Memory Addressing
Asked Answered
J

3

12

I'm taking this course, and I'm really struggling understanding the directive .align concept.
Here's an example, which I couldn't understand:

enter image description here

I know that inside the data segment, there are addresses, starting with 0x10010000,0x10010020,etc.

And I know, that inside each address, there are 8 memory fields, each has 32bit.

Now, what I don't understand is, how and why var2 inside the address 0x10010010? str1 is inside the address 0x10010003 because we reserved 3 bits for the var1.

The last thing is, what exactly the directive .align doing? When I tested it in Mars4, it only shifted the data into the next memory field when I used align 3 and up, but I don't really get it.

Jeroldjeroma answered 26/10, 2013 at 16:9 Comment(2)
there are 8 memory fields, each has 32bit. - Likely you were looking at a whole row of words in memory, in MARS's GUI. There are 4 addresses inside each word, addresses are 1 apart, not 0x20.Dewy
Related: details on how .align works in classic-MIPS assemblers like MARS, e.g. magically affecting previous labels, unlike in modern assemblers like GAS and clang: MARS MIPS simulator's built-in assembler aligns more than requested?Dewy
C
18

Alignment is important for a MIPS processor, it only likes to read multi-byte values from memory at an address that's a multiple of the data size.

The .ASCIIZ field can be placed anywhere since a string is read one byte at a time. So putting it at 0x10010003 is fine.

The .WORD field must be aligned to a multiple of 4. So it can't be put at 0x1001000E, the next available location after the string. The assembler intentionally shifts the value and leaves two bytes unused. To the next address that's a multiple of 4, 0x10010010.

The .ALIGN directive is a way to override the default alignment rules. The next field after the directive will be aligned to a multiple of 2 to the power of n where n is the .ALIGN value. In your case that's pow(2, 3) = 8 bytes.

Which is what you see happening, without the .ALIGN directive the .HALF field would be stored at 0x10010014. Not a multiple of 8 so it is moved to 0x10010018.

The example is otherwise artificial, no obvious reason to use the .ALIGN directive here since .HALF only requires an aligment to a multiple of 2 so storing it at 0x10010014 would have been fine.

Carmelcarmela answered 26/10, 2013 at 16:27 Comment(6)
Was typing my answer on phone while there was none...yours would have obviated the need for another one.Hamford
Thanks you everyone for your answers! Question: How 0x10010010 is a multiple of 4?Jeroldjeroma
0x10010010 = 2^28 + 2^16 + 2^4, which is a multiply of 4. If the calculation makes no sense to you, please read up again on hexadecimal numbers.Hamford
Actually, if I refer to hex numbers, I should write this instead as 0x10010010 = 16^7 + 16^4 + 16^1.Hamford
4 is a multiple of 4. 8 is a multiple of 4. 12 is a multiple of 4. Keep going for a while and you'll find that 0x10010010 is a multiple of 4. 0x10010010 / 4 == 16781328 / 4 = 4195332.0 No remainder.Carmelcarmela
Thanks! It's very clear and I did well in my quiz. Much appreciated.Jeroldjeroma
H
3

Certain assembly directives imply that data is stored aligned, which means starting at an address that is a power of two. Recall first a couple of conventions in MIPS: 

(1) a "word" is 4 bytes (you will sometimes see it defined as 2 bytes),

(2) a halfword (.half) are 2 bytes, and

(3) .asciiz null terminates the string (as in C).

Using this, you already explained how var1 and str1 are stored. Why the buffer of 2 empty bytes before var2? Because it is declared a .word, and (by (1) above) will so be stored beginning at a memory location that is a multiple of 4. Had you declared it a .half, you'd have no 2 empty bytes between str1 and var2.

var2 is declared a .half - it is a 16 bit (2 byte) address which fits into one. However, before declaring it the alignment is changed to 3. Now, check the first sentence: this is the power you raise 2 to; so we actually align to 8. This means that until overridden, variables will be placed as declared, but additionally their initial storage location must be a multiple of 8. Hence, the assembler inserts 4 empty bytes to store var3 at a multiple of 8. 

Hamford answered 26/10, 2013 at 16:42 Comment(0)
D
0

And I know, that inside each address, there are 8 memory fields, each has 32bit.

isn't MIPS memory byte-addressable? which means that each memory address references an 8-bit quantity

Dracula answered 27/1, 2022 at 22:43 Comment(1)
Yes, likely they were looking at a whole row of words in memory, in MARS's debugger GUI, where the next row might well be 0x20 further on. And the GUI is pretty word-oriented at least by default, only showing columns within each row for words.Dewy

© 2022 - 2024 — McMap. All rights reserved.