1
\$\begingroup\$

I am continuing my practice with MIPS assembly and machine code. I am doing a problem that assumes the following:

• variables a-j are assigned temporary registers $0-$8.
• the base address of arrays A and D are in $9 and $10.
• if need register to store an intermediate result, use remaining temporary or saved registers or register $at. 

$0 - a    $1 - b
$2 - c    $3 - d
$4 - e    $5 - f
$6 - g

These are the problems:

a) f = a - 20 + b + c - d;
b) D[i] = A[j] << 6;
c) f = g - A[D[5]]

This is my attempt:

a) addi $0, $0, 101100
   add $5, $1, $2
   add $5, $5, $0
   sub $5, $5, $3

As for b) and c), I am not too sure how to do start it. I have attempted to find examples online but haven't been able to and the examples I'm going off of aren't that great.

If anyone can check and see if there is any issues or if you have any advice/help, Id appreciate it Thank you.

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

To the different tasks:

  • a) your answer seems correct to me.

  • b) I think it is meant, that the arrays A and D are located in the RAM and start at the addresses stored respectively in $9 and $10.

    1. First you have to take the value of j and multiply it with 4 (you need a byte offset for the memory: the numbering follows bytes and not words, so you have to take it four times if you want the jth word (32 bit) and not byte (8 bit) in the array!).
      --> maybe it is better to store the value directly in a temporary register ($at, ...) so j doesn't get destroyed.

    2. Now you add the absolute memory base adress of the array (stored in $9) to have the absolute adress of the data field we want to access.

    3. Then take the value and fetch the data at this adress in memory. The command for this should be lw $t, offset($s), where $t represents a temporary register to store the data, $s represents the absolute adress we just computed. Here we don't need the offset, so we use 0 or completely omit the value like this: lw $t, ($s).

    4. This value then has to be shifted left six times: the command is sll $d, $t, shamt where shamt is an immediate - in our case the number 6.

    5. Now we have to compute the absolute adress of our destination data field in array D (this works just like with A, only with i instead of j, but but you shouldn't use the same register where your data is stored, or you'd overwrite it).

    6. Finally store our value at the correct adress in RAM with an operation very similiar to lw, sw $t, offset($s), which works just like lw (and we still don't need any immediate offset to be added to our adress).

    Let me just append some information about the offset: it is used if you want to statically access a predefined element in A (that is not stored in register, but in immediate), e.g. the fourth. Then you would use "lw" for example like this: lw $at, 16($9) ..... Hang on a moment: Why 12, didn't we want the 4th element? - Yes we do, but using 4 would cause us to read the 2nd element (word) in the array, that is the 5th to 8th byte!
    Remember: memory is byte-adressed and not word-adressed. (You can use this for task c), too, but it can be solved also without.)

  • For c) you have to access array A with a relative adress equivalent to the data stored in the array D at position 5 (i.e. 6th element). This should be really easy after task b.

I hope I could clear some things up in general, in addition to helping with this particular problem :)

I didn't add the complete source code as I think it helps more to implement in on your own. With these detailed instructions it shouldn't be too difficult. If you still have trouble don't be afraid of asking further help!

If there are mistakes in here please tell me!

EDIT: now, that actual code has been posted I will add some too:
a)

subi $5, $0, 20 # f = a - 20
add  $5, $5, $1 # f = f - b
add  $5, $5, $2 # f = f + c
sub  $5, $5, $3 # f = f - d

b)

sll $at,  $8,   2   # at = j << 2;
add $at,  $at,  $9  # at = at + &A; (add base adress of A)
lw  $tmp, ($at)     # tmp = A[at];
sll $tmp, $tmp, 6   # tmp = tmp << 6;
sll $at,  $7,   2   # at = i << 2;
add $at,  $at,  $10 # at = at + &D; (add base adress of D)
sw  $tmp, ($at)     # D[at] = tmp;

c)

lw  $at, 20($10)     # at = D[5]; (5 * 4 bytes = 20, base address for D: $10)
sll $at, $at,    2   # at = at << 2;
add $at, $at,    $9  # at = at + &A; (add base adress of A)
lw  $at, ($at)       # at = A[at];
sub $5,  $6,     $at # f = g - at;
\$\endgroup\$
6
  • \$\begingroup\$ As I mentioned in my answer, I don't understand what the instructions are referring to when they say variable a is in $0. register 0 is read only (hard coded zero). So I went with symbolic names for the temporary registers. How did you interpret this? \$\endgroup\$
    – tcrosley
    Commented May 29, 2015 at 23:44
  • \$\begingroup\$ I think this is merely an abstraction for not having to bother about which registers can be used, and which not. But it would interest me too, which further temporary registers are to be used (as we need two in task c... if we don't want to push/pop registers). \$\endgroup\$
    – Fabio
    Commented May 29, 2015 at 23:53
  • \$\begingroup\$ What do you think: is adding two times or shifting once faster (when adding byte offset to adresses in b and c)? \$\endgroup\$
    – Fabio
    Commented May 29, 2015 at 23:56
  • \$\begingroup\$ First of all thanks to both of you. I got great insight and better practice bc of it. Instinctively, I tend to go with shifting but the adding two times made me understand better of what is going on. \$\endgroup\$
    – user655321
    Commented May 30, 2015 at 0:08
  • \$\begingroup\$ @Fabio shifting is probably a better choice. \$\endgroup\$
    – tcrosley
    Commented May 30, 2015 at 22:21
0
\$\begingroup\$

The instructions say:

• variables a-j are assigned temporary registers $0-$8.
• the base address of arrays A and D are in $9 and $10.

This is confusing; if they refer to register numbers, this doesn't work because the first register is a constant 0. If they refer to the temporary registers, this is better except there is no $t10. But I am going to assume the latter, and use $s0 instead of $10 for the base address of D. If this is wrong, you'll need to adjust things. I also used $s1 as a temporary in addition to $at.

For b) and c), you need to compute an address and then use base addressing (used by the lw and sw instructions) to access the computed location.

My attempts:

a) f = a - 20 + b + c - d;

addi    $at,$a0,-20 # (no subi)   temp = a - 20
add     $at,$at,$t1 # +b          temp += b
add     $at,$at,$t2 # +c          temp += c
sub     $t5,$at,$t3 # -d          f = temp - d

which is essentially the same as your except I don't destroy any original values.

b) D[i] = A[j] << 6;

add $at, $t8, $t8   # temp = j * 2     (need to multiply index by 4 because 
add $at, $at, $at   # temp = temp * 2  MIPS address are 4 bytes long)
add $at, $at, $t9   # temp = &A + temp (now have address of A[j] in temp)
lw  $s1, 0($at)     # $s1 = A[j]       (get value)
sll $s1, $s1, 6     # $s1 = s1 << 6
add $at, $t7, $t7   # temp = i * 2
add $at, $at, $at   # temp = i * 2
add $at, $at, $s0   # temp = D + temp  (now have address of D[i] in temp)
sw  $s1, 0($at)     # D[i] = $s1       (store result)

c) f = g - A[D[5]];

lw  $at, 5*4($t10)  # temp = D[5]
add $at, $at, $at   # temp = D[5] * 2
add $at, $at, $at   # temp = temp * 2
add $at, $at, $t9   # temp = &A + temp (now have address of A[D[5]]
lw  $s1, 0($at)     # $s1 = A[D[5]] (get value)
sub $t5, $t6, $s1   # f = g - $s1
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.