3

I am learning MIPS assembly language. This is an exercise I am trying to understand. The question is:

What does the following code correspond to?

Name:   move    $t0,    $zero
Loop:   add     $t1,    $t0,    $t0
        add     $t1,    $t1,    $t1
        add     $t2,    $a0,    $t1
        sw      $zero,  0($t2)
        addi    $t0,    $t0,    1
        slt     $t3,    $t0,    $a1
        bne     $t3,    $zero,  Loop
        jr      $ra

I already know the meaning of each instruction, how the directives work and what a for loop is. When I try to run the code in MIPS Mars Simulator it ends with error, probably because values contained in the registers $a0 and $a1 are needed to begin with.

I don't get the bigger picture. What happens during each loop iteration? Is it just a part of a bigger algorithm? What is it supposed to do?

  • By the looks of it it just clears a chunk of memory (sets each element to 0). – Michael Feb 04 '19 at 15:22
  • @Michael Yeah, however why is it doubling `$t0` each time? That's what confuses me. – m0skit0 Feb 04 '19 at 15:24
  • 3
    It's actually calculating `$t0 * 4` (because each element in the array is 4 bytes). But I have no idea why they did it with two additions instead of `sll $t1, $t0, 2`. – Michael Feb 04 '19 at 15:30
  • 2
    @m0skit0: it's just a convoluted way to move the target address 4 bytes on each iteration. `$t0` holds the index of the word array to be zeroed, then it "multiplies" it by 4 by issuing the two adds – gusbro Feb 04 '19 at 15:31
  • 1
    @m0skit0 Does it mean that $a1 (supposedly y) number of memory addresses starting from the address contained in $a0 (supposedly addr(x) ) are set to 0 and then the loop ends? – firstName lastName Feb 04 '19 at 15:38
  • 1
    Please check and improve my answer. Thank you. – firstName lastName Feb 04 '19 at 16:19
  • @Michael For most CPUs, adding is faster than bit shifting if you're bit shifting by a small amount like 1 or 2. This isn't just a MIPS thing – puppydrum64 Dec 02 '22 at 14:27

1 Answers1

3

Reading the comments I guess the answer is somehow clearer. At the beginning of the code, $a0 and $a1 should already have some value, let's suppose x and y respectively.

The first line move $t0, $zero would be int i = 0; in high level programming language, or the initial value of a do-while (condition) loop.

The following:

Loop: add $t1, $t0, $t0
      add $t1, $t1, $t1

is when the loop begins and would be like:

int j = 2 * i;
    j = 2 * j;

which shortly means int j = 4 * i; , the iterator is multiplied by 4 because MIPS registers are made of 32 bits, which means 4 bytes.

Then add $t2, $a0, $t1 corresponds to int k = x + j; or in other words to int k = x + 4 * i.

The next instruction sw $zero, 0($t2) stores 0 into the memory whose address is offset by 0 from the address of the value contained in $t2.

addi $t0, $t0, 1 increments i++; and

slt  $t3,  $t0,   $a1
bne  $t3,  $zero, Loop
jr   $ra

checks if i < y is satisfied, which is the condition of the do - while (i < y) loop. In case it is still true, the loop goes on setting to 0 the next element in memory, otherwise the loop ends returning to $ra.

  • Instead of `int k = x + j;`, I'd write either `uintptr_t` or `void *`. I mean yes in asm everything is just an integer, but if you're using C terminology, you might as well keep track of which integers are addresses of valid memory and going to be dereferenced later. – Peter Cordes Feb 05 '19 at 00:28
  • It's not a `for`-loop. – EOF Feb 05 '19 at 05:30