I'm trying to learns the MIPS ISA. If I want to do this function in MIPS:
A[2*i]=A[2*k+j];
How would I go about this? I would also appreciate any other content that I can read, i.e links where I can read up on how to solve this kind of problem.
We can break this down to 2 parts:
Calculate the addresses of A[2*i] and A[2*k+j]
Assign the value at the second address to memory at the first address
I'm only going to address (ahem) #1.
To calculate the address of an array element, you need to know 3 things:
The address of the start of the array
The index of the element you want
The size of the array elements
I assume you know how to compute, or just know, #1 & #3. That leaves #2, which involves simple arithmetic. (Since you haven't indicated how i, j & k are represented, I can't help too much there).
The final step, then, is to multiply the index by the size of an array element; this gives you the offset of your desired element from the start of the array. Add that to the address of the start of the array, and you have your element's address.
P.S. The code you're translating doesn't swap two elements; it copies one over the other.
It's been a while, but this could be close. You'll never learn assembly language without trying youself. Make more examples and code them. More study material here .
# int calc(int *A, int i, int j, int k)
# {
# return A[2 * i] = A[2 * k + j];
# }
# Args: a0=A, a1=i, a1=j, a3=k Rtn: v0
.text
.set nomacro
.set noreorder
.global calc
.ent calc
calc:
sll $t0, $a1, 3 ; t0 = i * 8
sll $t1, $a3, 1 ; t1 = k * 2
add $t1, $t1, $a1 ; t1 += j
sll $t1, $t1, 2 ; t1 *= 4
add $t0, $t0, $a0 ; t0 += A
add $t1, $t1, $a0 ; t1 += A
lw $v0, 0($t1) ; r = A[4 * (2 * k + j)]
sw $v0, 0($t0) ; A[4 * (2 * i)] = r
.end calc
Related
I am doing a homework problem for the computer design and architecture class where we are required to implement a simple for loop in C, into MIPS using the MARSim. I implemented the for loop step by step, initialized (if that is the proper term) the variables in memory, yet when I assemble and run it throws this error: question1.asm line 11: Runtime exception at 0x00400008: address out of range 0x00000000
I've looked at line 11 : lw $t1, 0($a1),
and as I understand it, this should work properly. As I understand here we are setting our t1 value to a1 (b[i]).
Here is the C we have to reproduce:
for (i=0; i<=100; i++) { a[i] = b[i] + C ; }
Here is my attempt:
# t0 = i
# t1 = b[i]
# t2 = a[i]
# t3 = 101 (the end value of i)
# s0 = c
# $a0 = a
# $a1 = b
begin:
addi $t3, $zero, 101 #loop terminate value
add $t0, $zero, $zero # set our counter to zero
loop: lw $t1, 0($a1) # set t1 to b[i]
add $t1, $t1, $s0 # B[i] + c
sw $t1, 0($a0) #store $t1 into a[i]
addi $t0, $t0, 1 # loop increment
addi $a0,$a0,4 # increment a0 to point to the next block in the array (4 bits)
addi $a1, $a1, 4 # likewise with b[i]
beq $t0, $s0, finish
finish:
The MIPS code I've written, should mimic the action of the C code w/o error. However on the first iteration of the loop it states it is accessing an out of range address 0x00000000. Could someone shine some light on what I am doing wrong? I would really appreciate a thorough explanation so I can understand this better for my class. Thanks for your assistance and much love.
Cheers.
I came across this problem that asks to convert from c to MIPS code.
B[8] = A[i-j];
where $s6 and $s7 stores the base address of array A and B. i and j are stored in $s3 and $s4.
This is my solution:
sub $t0,$s3,$s4 # i - j
sll $t0,$t0,2 # (i - j) * 4
add $t0,$s6,$t0 # A + (i - j) * 4
lw $t1,0($t0) # *(A + (i - j) * 4)
sw $t1,32($s7) # *(B + 32) = *(A + (i - j) * 4)
This is the solution given to us:
sub $t0, $s3, $s4
add $t0, $s6, $t0
lw $t1, 16($t0)
sw $t1, 32($s7)
The solution given to us doesn't make any sense to me as it certainly fails almost all cases as the address might not be word aligned. Does anyone think that the solution given to us is correct?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I was trying to solve this and convert it to MIPS assembly code
but the answer in the book confused me.so, can anyone explain how this code get this result in c ?
B[g] = A[f] + A[f+1];
I have inserted comments for what I think that's right please correct me if I was wrong.
Assume we have variables f, g, h, i, j stored in $s0, $s1, $s2, $s3 and $s4, respectively. Assume the base addresses of arrays A and B are at $s6 and $s7.
The code:
add $t0, $s6, $s0 #This will add f bytes to the base address and it's not equal to A[f].
add $t1, $s7, $s1 #This will add g bytes to the base address and it's not equal to B[g]
lw $s0, 0($t0) #This will point to the value in (f +base address of A +0) bytes
lw $t0, 4($t0) #This will point to the value in (f +base address of A +4) bytes
add $t0, $t0, $s0
sw $t0, 0($t1)
Your compiled fragment annotated by me:
add $t0, $s6, $s0
add and store in register t0 whatever is in register s6 and s0. Since you have pointed out that f is stored in s0 and the base address of A is stored in s6, this adds the addresses in preparation for a register indirect load later on. More simply A[f] == *(A + f) in C, and this is preparing for the (A + f) de-reference later on.
add $t1, $s7, $s1
The same thing happening for B and g. Add their contents and store them in an intermediate register, to be later used as address based de-reference targets.
lw $s0, 0($t0)
This is loading to the s0 register, using what's known as the register-indirect addressing mode of the cpu, whatever is at the address pointed to by t0 plus 0 bytes. In c this is equal to s0 = *(A + f).
lw $t0, 4($t0)
The same thing as above, only that this time it loads to register t0 whatever is pointed at t0 plus 4 bytes. Equal to C t0 = *(A + f + 1).
add $t0, $t0, $s0
This is the point where it performs the addition in your code. It's equal to the C code fragment of A[f] + A[f + 1].
sw $t0, 0($t1)
This is storing the result of the previous addition to the address pointed to by t1.
~~~~~~~~~~~
If you are looking for some references for the code you have, I found both this MIPS instruction set reference useful and, of course, Matt Godbolt's interactive compiler.
If you want to see what code does what using the interactive compiler, just wrap your code in a void function, select as the compiler x86 clang and at the compiler options --target=mips. Then from the filter apply colourise, and you will be able to see what C code generates what assembly code, to get something like the image below
add $t0, $s6, $s0 # t0 = A + f
add $t1, $s7, $s1 # t1 = B + g
lw $s0, 0($t0) # s0 = *(t0 + 0) = *(A + f) = A[f]
lw $t0, 4($t0) # t0 = *(t0 + 4) = *(A + f + 1) = A[f+1]
add $t0, $t0, $s0 # t0 = t0 + s0 = A[f] + A[f+1]
sw $t0, 0($t1) # *(t1 + 0) = *(B + g) = B[g] = t0
Remember that C pointer arithmetic scales by item size, but assembly uses bytes. Hence, advancing 4 bytes is advancing 1 item in C.
On second thought, this in fact means f and g should also be scaled by 4, which they don't seem to be.
sll $t0, $s0, 2 # $t0 = f * 4
add $t0, $s6, $t0
sll $t1, $s1, 2 # $t1 = g * 4
add $t1, $s7, $t1
lw $s0, 0($t0)
lw $t0, 4($t0)
add $t0, $t0, $s0
sw $t0, 0($t1)
Yes, the code is missing these two lines, you just need to scale both f and g by 4.
So I have an assignment problem which asks for a for loop in C to be converted into MIPS. My professor moves extremely fast so I couldn't catch half of what he said. Here is the code:
for (i=0; i<10; i++){
a[i] = b[i] + c[i];
}
This fragment is stored in memory starting from location 00000100 Hex.
Convert this code to MIPS and provide numeric offsets for each branch or jump instruction used.
I don't quite understand the use of offsets. From the lecture slides given to us, it seems load word and store word commands are used for the offsets, which are also used for the arrays but I'm not sure how to go about it. Below is something I put together based on other solutions I saw, but am of course open to changes. I'm hoping it's at least going in the right direction. Any help would be appreciated.
#t0 = i
#s0 = a
#s1 = b
#s2 = c
#t3, t4, t5, t6, t7 = free
loop:
bgt $t0,9,exit #exit before i reaches 10
addi $t3,$s1,$t0 #temp reg $t3 = address of b[i]
addi $t4,$s2,$t0 #temp reg $t4 = address of c[i]
lw $t5,0($t3) #temp reg $t5 = c[i]
lw $t6,0($t4) #temp reg $t6 = a[i]
add $t3,$t5,$t6 #temp reg $t10 = b[i] + c[i]
addi $t7,$s0,$t0 #temp reg $t7 = address of a[i]
sw $t3,0($t7) #store word a[i] = b[i] + c[i]
addi $t0,$t0,1 #increment i by 1
j loop #jump to start of loop
exit:
From what I can see, you are storing it in the same index each time. In MIPS, every 4 bytes is a word, so you must store it in 0, 4, 8, etc. Also, you need to allocate memory for your array before you start using one. Here's an example.
li $v0, 9 # create an array, start address in $v0
li $a0, 80 # allocate 80 bytes, or 20 words
syscall
move $t0, $v0 # move from $v0 (temp) to $t0
Check out this tutorial and see if it helps at all.
I am attempting to create an algorithm that finds the trace of an n-by-n square matrix A.the trace of an n-by-n square matrix A is defined to be the sum of the elements on the main diagonal (the diagonal from the upper left to the lower right) of A.The main idea involved is that at this level multi-dimensional arrays are stored as one-dimensional arrays, and the multi-dimensional indexing (for a matrix with m rows and n columns) is converted to one-dimensional indexing.As I'am unfamiliar with mips attempts to integrate it into code are unsuccessful my latest attempt below.
I have set the registers to the following:
$a0 = base address of array (matrix), a
$a1 = n, number of rows and columns
$v0 = trace
$t0 = i
trace: move $v0, $zero
move $t0, $zero
bne $t0,$a1,end
sll $t1,$a0,4
add $t1,$t1,$t0
sll $t1,$t1,2
add $t2,$t1,$a0
lw $t0,0($t1)
addi $sp, $sp, 8
sw $t1,0($t0)
j trace
end: jr $ra
but to no avail the answer does not come out as desired the format of the algorithm should be as follows;
trace = 0
for i = 0 to n-1
trace = trace + a[i,i]
end for
I have added some comments indicating suspicious behaviour
trace: move $v0, $zero
move $t0, $zero
loop: bne $t0,$a1,end
sll $t1,$a0,4 ; t1 = a0 * 16, a0 is the base address, should probably be $t0
add $t1,$t1,$t0
sll $t1,$t1,2
add $t2,$t1,$a0
lw $t0,0($t1)
addi $sp, $sp, 8 ; What are you doing with $sp? perhaps this should be add $v0,$v0,$t0
sw $t1,0($t0) ; What are you storing here?
j trace ; This should probably jump to loop, or the code will never end
end: jr $ra
Also note that the sll assumes that the size of your matrix is 16.