Writing MIPS assembly and machine code for instructions

assemblycodemipsregister

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.

Best Answer

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;