I need to translate some MIPS assembly instructions to C code. I think I got it, but it seems counter-intuitive. Any help? We have variables f, g, h, i, j stored in registers $s0, $s1, $s2, $s3 and $s4 respectively. The base of arrays A and B are stored in $s6 and $s7 respectively. 4 byte words. Comments in the code are my own.
addi $t0, $s6, 4 # $t0 = A[1]
add $t1, $s6, $0 # $t1 = A[0]
sw $t1, 0($t0) # $t0 = A[0]
lw $t0, 0($t0) # $t0 = A[0]
add $s0, $t1, $t0 # f = A[0] + A[0]
I just feel like I'm wrong. Why make $t0 A[1] first if we never use it?
I think you have got in completely wrong.
addi $t0, $s6, 4 # $t0 = A[1]
After the addi, register $t0 became the memory address of A[1], which would be &A[1], not A[1]. To get value of A[1], you need to use lw after you done the addi
lw $t0, 0($t0) # $t0 =A[1]
sw $t1, 0($t0) # $t0 = A[0]
You've got this back-to-front. It is a store, so it is used:
sw $t1, 0($t0) # A[1] = $t1
Just a little addition to the previous answers:
The store word means that you cannot access $t1 anymore because it is copied to memory. At least you should not use the $t1 from the store word instruction. You should use the one before (add $t1, $s6, $0). This means that the answer is f ( which is in $s0) = &A[0] (base address in register $t1) + A[1] (value of the array with word index 1, which is in register $t0)
Mnush's answer is incorrect.
The last line is adding $t1 and $t0.
$t1 = A[0] and
$t0 = A[1].
With proper comments:
addi $t0, $s6, 4 # $t0 = &A[1]
add $t1, $s6, $0 # $t1 = &A[0]
sw $t1, 0($t0) # A[0] = A[1]
lw $t0, 0($t0) # $t0 = A[0]
add $s0, $t1, $t0 # f = A[0] + A[1]
The C Code:
A[1] = A[0];
f = A[0] + A[1];
Actually you are using A[1] twice as shown:
Register $t0 carries the address of the array from the first instruction
sw $t1, 0($t0) # A[1] = $t1 => A[1] = &A[0]
Load the value of the address ($t0 + 0) into register $t0
lw $t0, 0($t0) # $t0 = A[1]
Essentialy =>
$t0 = &A[0]
addi $t0, $s6, 4 # $t0 = &A[1]
add $t1, $s6, $0 # $t1 = &A[0]
sw $t1, 0($t0) # A[1] = &A[0]
lw $t0, 0($t0) # $t0 = A[1]
add $s0, $t1, $t0 # f = &A[0] + A[1]
C code:
f = &A[0] + A[1]
Guess this is correct.
A[1] = A[0]
f= A[1] + A[1]
Related
I'm very new to MIPs and trying to create a for loop for an assignment.
for (int i=1; i < 16; i+=2)
{
A[i] = A[i] + B[3*i]
}
With the current code I have when I try to load the value of A[i] it says fetch address not aligned on word boundary.
Here is my code:
main:
li $t0, 1 # Starting index of t0=i
lw $s7, aSize # Loop bound
la $s0, A # &A
la $s6, endA # &endA
la $s1, B # &B
loop:
#TODO: Write the loop code
addi $t3, $zero, 3 # $t3 = 3
mul $t4, $t0,$t3 # $t4 = i * 3
sll $t4, $t4, 2 # $t4 into a byte offset
add $s1, $s1, $t4 # $s1 = &B[i*3]
add $s0, $s0, $t0 # $s0 = &A[i]
lw $t1, 0($s0) # value of A[i]
lw $t2, 0($s1) # value of B[i * 3]
add $t2, $t1, $t2 # A[i] + B[i]
sw $t2, 0($s0) # A[i] = A[i] + B[i]
addi $s0, $s0, 2
addi $s1, $s1, 2
addi $t0, $t0, 1 #i++
bne $t0, $s7, loop
I'm very new to MIPs so not sure whats going on or where to even look. I appreciate any help.
When you do:
mul $t4, $t0,$t3 # $t4 = i * 3
You are calculating the array index [as you would in c].
But, before you can add that to the base address of the array, you need to convert this index into a byte offset. That is, you have to multiply it by 4. This can be done [as in c] with a shift left of 2.
So, after the mul, do:
sll $t4,$t4,2
You have to do this multiply/shift for all index values before adding them in.
UPDATE:
Okay that makes sense. I added that in but I'm still getting that word boundary error on the line "lw $t1, 0($s0)"
You're not showing the definition of A or B, so there could be an alignment issue.
When you do:
add $s1, $s1, $t4 # $s1 = &B[i*3]
You are modifying the original/base value of &B[0]. That's not what you want. Use a different register for the final address value (i.e. leave $s1 unchanged throughout the loop)
Do something like:
add $s3, $s1, $t4 # $s3 = &B[i*3]
lw $t2, 0($s3) # value of B[i * 3]
Adjust other similar register usage in a similar manner (i.e. you have a similar problem with the A array)
I've coded up a cleaned up version. I've not assembled nor tested it, but I think it will get you closer. This may have an off-by-one error [it's hard to tell without the entire program] as I'm not sure what aSize is.
main:
li $t0,1 # Starting index of t0=i
lw $s7,aSize # Loop bound
la $s0,A # &A
la $s6,endA # &endA
la $s1,B # &B
addi $t3,$zero,3 # $t3 = 3
loop:
# TODO: Write the loop code
mul $t4,$t0,$t3 # $t4 = i * 3
sll $t4,$t4,2 # $t4 into a byte offset
add $s3,$s1,$t4 # $s3 = &B[i*3]
sll $t4,$t0,2 # $t4 into a byte offset
add $s2,$s0,$t4 # $s2 = &A[i]
lw $t1,0($s2) # value of A[i]
lw $t2,0($s3) # value of B[i * 3]
add $t2,$t1,$t2 # A[i] + B[i]
sw $t2,0($s2) # A[i] = A[i] + B[i]
addi $t0,$t0,2 # i += 2
bne $t0,$s7,loop
Could someone help walk me through what some lines in this MIPs code are doing?
The C code is B[8] = A[i - j] with i = $s3, j = $s4, &A[] = $s6, and &B[] = $s7
The MIPs code is as follows...
sub $t0, $s3, $s4 # i - j
sll $t0, $t0, 2 #Gets the offset of 8 for B[]
add $t0, $s6, $t0 #Goes to the offset in B[] ?
lw $t1, 0($t0) #????
sw $t1, 32($s7) #????
I get a bit lost once it gets to the last 3 lines.
Why is it 0($t0) and 32($s7)? Or just why 0 and 32?
sll $t0, $t0, 2 // This multiplies (i-j) * 4, not 8. Because the indexes are 4-byte ints
add $t0, $s6, $t0 // $t0 = A + (i-j)*4. So $t0 = &A[i-j]
lw $t1, 0($t0) // $t1 = A[i-j]
sw $t1, 32($s7) // B[32/4] = $t1
32($s7) means $s7 + 32. The reason you add 32 because you are accessing the 8th element of an integer array, which is located in the memory address B + 8*sizeof(int) = B + 32
int MyArray[30];
int n = 2;
MyArray[0] = 1;
MyArray[1] = 1;
do{
MyArray[n] = MyArray[n-1] + MyArray[n-2];
n++;
}
while(n < 30);
While I was doing this I got stuck on how i can recursively call the function without the use of return address $ra or $sp since the code doesn't actually return anything.
This is my work so far :
#s1= Myarray[0]
addi $s0, $0, 2 #$s0=n=2
addi $t0, $s1,0
addi $t1,$0,1
sw $t1, 0 ($t0) #Myarray[0]=1
addi $t0,$t0,4
sw $t1, 0 ($t0) #Myarray[1]=1
add $t0,$s0,$s1 #MyArray[n]= Myarray[0] +n
Loop:
addi $t2,$t0,-4
addi $t3,$t0,-8
lw $t4,0 ($t2)
lw $t5,0 ($t3)
add $t5,$t4,$t5
sw $t5, 0 ($t0)
addi $t0, $t0 ,4
addi $s0,s0,4
slti $s6,$s0,30
beq #s6,$0,Exit
j loop
Exit
This code
sw $t1, 0 ($t0) #Myarray[0]=1
addi $t0,$t0,4
sw $t1, 0 ($t0) #Myarray[1]=1
add $t0,$s0,$s1 #MyArray[n]= Myarray[0] +n
should be
sw $t1, 0 ($t0) #Myarray[0]=1
addi $t0,$t0,4 #update 't0' to point to Myarray[1]
sw $t1, 0 ($t0) #Myarray[1]=1
addi $t0,$t0,4 #update 't0' to point to Myarray[2]
The error is in the last line. Note that $s1 points to the array, and $s0 has the value 2, so t0=s1+s0 points t0 to the wrong address. You really want t0=s1+(s0*4) since each int is four bytes.
However, since you've already updated t0 to point to Myarray[1] (in the second line), you can just update it again (in the fourth line).
Just started learning assembly for one of my classes and I am a bit confused over this code segment. This is from a textbook question which asks you to translate from MIPS instructions to C. The rest of the question is in the attached image.
For the MIPS assembly instructions above, what is the corresponding
C statement? Assume that the variables f, g, h, i, and j are assigned to registers $s0, $s1, $s2, $s3, and $s4, respectively. Assume that the base address of the arrays A and B are in registers $s6 and $s7, respectively.
sll $t0, $s0, 2 # $t0 = f * 4
add $t0, $s6, $t0 # $t0 = &A[f]
sll $t1, $s1, 2 # $t1 = g * 4
add $t0, $s6, $t0 # $t1 = &B[g]
lw $s0, 0($t0) # f = A[f]
addi $t2, $t0, 4
lw $t0, 0($t2)
add $t0, $t0, $s0
sw $t0, 0($t1)
I have a basic understanding of some MIPS instructions but frankly, the stuff with arrays confuses me a bit. Could anyone here point me in the right direction? Thanks!
It's been a while since I last wrote MIPS assembly. However, from what I can understand from the first few instructions:
sll $t0, $s0, 2 # t0 = 4 * f
add $t0, $s6, $t0 # t0 = &A[f]
s0 holds the index f at which you want to access array A. Since you multiply f by 4, A is an array of some datatype with 4 bytes length (probably an int). s6 is holding the array address, because to access the address of A[f] you would essentially do (in pseudocode)
address_of_A[f] = base_address_of(A) + offset_of_type_int(f)
The same stuff in principle happens in the next 2 instructions, but this time for array B. After that:
lw $s0, 0($t0) # f = A[f]
addi $t2, $t0, 4 # t2 = t0 + 4
The first load is obvious, s0 gets the value at address t0, which is of course A[f]. The second increments t0 by 4 and stores it to t2, which means that t2 now contains the address &A[f+1], since we know that array A contains 4-byte data.
The last lw command:
lw $t0, 0($t2)
stores the value at address $t2 on $t0, so $t0 is now A[f+1].
I am working on a project and can't seem to figure out what I am doing wrong. I am translating a piece of C code into MIPS Assembly Language.
The C Code is as follows:
int A[10];
int sum = 0;
int i = 0;
while(i < 10){
sum += A[i++];
sum *= 2;
}
I have produced the following MIPS code
where $s1 is base address of A
$s2 is sum
$s3 is i
s4 is 10
loop:
beq $s3, $s4, exit #if s3 and s4 equal, go to else
add $t0, $s3, $s3 #2i
add $t0, $t0, $t0 #4i
add $s1, $s1, $t0 #A[i]
lw $t2, 0($s1) #t2 = A[i]
add $s2, $s2, $t2 #sum = sum + A[i]
addi $s3, $s3, 1 #i = i + 1
add $s2, $s2, $s2 #sum = sum * 2
j loop
While my code produces a value, it doesn't match the expected value. I have been banging my head on the desk for hours trying to see what I am doing wrong and I can't figure it out. Any help is very much appreciated
You're adding $t0 to $s1 every time you loop over. As such, instead of incrementing the array pointer by 4 each time, you increment by i*4 each time.
So, instead of getting A[0], A[1], A[2], A[3], ..., you actually get A[0], A[1], A[3], A[6], ...
My suggestion would be to remove the first two add instructions, and just do add $s1, $s1, 4.
Polynomial is right, here is a fixed version of your code:
.text
.globl main
main:
li $s4 , 4
li $s3 , 0
la $s1 , array1
loop:
beq $s3, $s4, exit #if s3 and s4 equal, go to else
lw $t2, 0($s1) #t2 = A[i]
add $s2, $s2, $t2 #sum = sum + A[i]
addi $s3, $s3, 1 #i = i + 1
add $s2, $s2, $s2 #sum = sum * 2
addi $s1, $s1, 4 #$s1 = &(A[i++])
move $a0, $s2
jal print_int
j loop
exit:
li $v0, 10 # Exit
syscall
print_int:
li $v0, 1
syscall
la $a0, space
li $v0, 4
syscall
jr $ra
.data
array1: .word 3, 0, 1, 2
space: .asciiz " "