0

I cant find a flaw in my instructions. In instruction 2, I am putting A[19] + 4 into register $t1.

Something is wrong

Screen-Shot-2022-06-09-at-5-15-17-PM.png

aflo7
  • 58
  • 5
  • 1
    Your out of bounds check at step 3 is of course wrong. `t1` does not go to zero. Other than that, you did not say what issues you have. – Jester Jun 09 '22 at 21:40
  • LOOP: beq $t1, $s0, EXIT would that be better? @Jester – aflo7 Jun 09 '22 at 21:42
  • Somewhat, but that would skip the first element of the array. The flowchart isn't ideal, because the usual fix would be to put the condition at the end not at the start. – Jester Jun 09 '22 at 21:44
  • Do you want the loop to execute for `$t1 = &A[0]`? If so, you need to check for equality to `&A[-1]`. Or check for loop exit *after* using the pointer, but before decrementing it for the next iteration. (That's a different loop structure from what the flow chart is suggesting, which forces an inefficient loop with an unconditional `j LOOP` at the bottom, but still not letting you save a register.) Maybe they want you to use `bltu` pseudo-instruction for the pointer compare, would assemble to `sltu` / `bnez`. Like `while(1) { if (ptr < &A[0]) break; ...}`. But no, they specify BEQ. – Peter Cordes Jun 09 '22 at 21:48
  • Try to consider what `A[19]+4 `would mean: at last element of the array, get its value stored there, then add 4 to that. – Erik Eidt Jun 10 '22 at 13:46

1 Answers1

1

This assignment is pretty tricky. I think the only way to use that loop structure with that number of instructions is to load from -4($t1), if you want to access every element once.

That means exiting when ptr == &A[0] is correct (beq $t1, $s0, EXIT), since you already accessed it as ptr[-1] last iteration.

That also avoids the problem of loading from A[n], one-past-the-end, a bug in your current code.

But I wouldn't describe t1 as "the current address"; it's the address + 4 of the element you're going to access this iteration. But this loop structure with a conditional branch at the top is inefficient anyway, not a pattern you'd want to memorize.

Normally you want to arrange things so there's a conditional branch at the bottom, going back to the top of the loop or falling through. You don't want a j LOOP with an if () break inside the body if you can avoid it by rotating the loop to put the condition at the bottom, even if that means peeling a couple instructions at the start or end.

For example:

In this case, the normal way to write this efficiently would be
endp = arr+n; ; for(p = arr ; p != endp ; p++) ...

   or     $s1, $zero, $zero  # sum=0:  move $s1, $zero
## for variable n, check that it's non-zero like beqz $n, skip_loop
   or     $t1, $s0, $zero    # p = A;  move $t1, $t0
   addiu  $t2, $s0, 80       # endp = A + n
LOOP:                        # do{
    lw     $t0, 0($t1)
    addiu  $t1, $t1, 4
    add    $s1, $s1, $t0        # sum += *p++  with trapping on signed overflow 
    bne    $t1, $t2, LOOP    # }while(p != endp)

One more instruction outside the loop, and one more register needed. Unless you don't need the base address of A after the loop, then you can just increment $s1 instead of copying it first.

But this is fewer instructions in the loop, so fewer instructions executed for n>=1, and same static code size. (Or smaller if we can destroy the pointer).

MIPS has lots of registers, so using one extra is usually not a problem. And unless your loop runs only a couple, spending an extra instruction inside the loop to use fewer registers is a false economy. Loops with the conditional branch not at the bottom are dumb, especially when it's easy to be sure they run at least 1 iteration, and when the condition is simple so it's easy to write it the more efficient way.

Also, I scheduled my instructions to not use the load result right after the load! No sense stalling an in-order pipeline unnecessarily. MIPS II and later made it safe to do that for correctness, but would still stall. A pointer increment is the perfect thing to do right after a load. (On a real MIPS with a branch delay slot, you'd reorder the add $s1, $s1, $t0 into the branch delay slot, so it's load / p++ / bne / sum+=.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847