Reputation: 75
I am struggling trying to convert a[i+1] = a[i-1] + b[4]
to assembly. Where $s0
is the address of a
, $s1
is the address of b
, and $s2
is the variable i
. Professor mentions it can be done in 6 steps.
I have:
addi $t0, $s2, 4 #i + 1
addi $t1, $s2, -4 #i - 1
lw $t2, $t1($s0) #load a[i-1] - I know this is wrong
lw $t3, 16($s1) #load b[4]
add $t4, $t2, $t3 #add a[i-1] + b[4]
sw $t4, $t0($s0) #save to a[i+1] - I know this is wrong
The areas I know where it is wrong, I know I can't use a register for the immediate, but I am unsure how to tackle this problem otherwise. I might also be doing this completely wrong, and any help is appreciated.
Upvotes: 2
Views: 759
Reputation: 33601
Here is some annotated code that I believe will work:
.text
.globl main
# main -- main program
#
# a[i + 1] = a[i - 1] + b[4]
#
# arguments:
# s0 -- address of a
# s1 -- address of b
# s2 -- i
#
# registers:
# t0 -- address of a[i]
# t1 -- value of b[4]
# t2 -- i << 2 (i.e. a byte offset)
# t3 -- value of a[i - 1]
# t4 -- a[i - 1] + b[4]
main:
sll $t2,$s2,2 # get i << 2
add $t0,$s0,$t2 # get &a[i]
lw $t3,-4($t0) # get a[i - 1]
lw $t1,16($s1) # get b[4]
add $t4,$t3,$t1 # sum them
sw $t4,4($t0) # a[i + 1] = sum
This is pretty close to the only sequence that can be used. The order of the lw
instructions can be flipped but, otherwise, the instructions must be those shown, except for using different registers to hold different values.
For clarity, each intermediate term/step got its own t
register. But, we can reduce the number of registers used if reassign/reuse registers. For example, in the first two instructions, we could replace $t2
with $t0
, as we never use $t2
after that.
An optimizing compiler could/would do this. We'd end up needing only $t0-$t2
instead of $t0-$t4
:
.text
.globl main
# main -- main program
#
# a[i + 1] = a[i - 1] + b[4]
#
# arguments:
# s0 -- address of a
# s1 -- address of b
# s2 -- i
#
# registers:
# t0 -- i << 2
# address of a[i]
# t1 -- value of b[4]
# t2 -- value of a[i - 1]
# sum of a[i - 1] + b[4]
main:
sll $t0,$s2,2 # get i << 2
add $t0,$s0,$t0 # get &a[i]
lw $t2,-4($t0) # get a[i - 1]
lw $t1,16($s1) # get b[4]
add $t2,$t2,$t1 # sum them
sw $t2,4($t0) # a[i + 1] = sum
If the code is part of a function, we could use $v0, $v1, $a0
as our temp registers as a function is permitted to use $v0-$v1
and $a0-$a3
as internal temporaries if it wishes.
UPDATE:
The comments definitely help me understand what is occurring during each instruction
Good programming style [and therefore understanding] has lots of comments. Of the right type. This is particularly important for asm because in C, a variable like number_of_users
is somewhat descriptive. But, $t0
isn't.
The comments I added are what I would do for any asm code I would write for myself. And, I've been writing asm for decades.
Also, the "optimized" version has a purpose: Simplification. By freeing up $t3-$t4
, they can be used to hold other things. In a more complex function, this can make the difference between a simple and easily understood one, and a needlessly complicated one that is harder understand and maintain.
For more on this, and tips on how to write asm well, based on my own experience, see my answer: MIPS linked list
the professor is not the greatest at relaying information
There is only so much that can be conveyed in a classroom setting. It can cover the basics. And, the coursework can help you learn the basics of the given language. And, IMO, professors have never been particularly good at commenting code well [enough ;-)].
When I was learning asm [on a different architecture], in addition to coursework, I was also able to work as paid programmer on a multiuser timesharing OS that was written 100% in asm. It had the same style of commenting as above.
IMO, one of the best ways to learn is analyze "expert" code. Ask the question: "Why did they do that in that way?". That's what I did and I learned a lot. I [still] give credit to that experience to this day.
Upvotes: 3
Reputation: 71516
temp0 = $s0 + $s2
temp2 = load -4(temp0)
temp3 = load 16($s1)
temp1 = temp2 + temp3
store +4(temp0) = temp1
Upvotes: 1