Home > Software engineering >  How to use the set if less than (SLT) statement in a for-loop in MIPS 32?
How to use the set if less than (SLT) statement in a for-loop in MIPS 32?

Time:09-27

I'm working on some homework and my issue is I'm supposed to include the SLT (set if less than) line in this for-loop assembly but I'm not sure how to do that. I found this question helpful but I can't use the BLT (branch if less than) statement, the professor did introduce macros but this question specifies to use SLT. I ended up just using it in my assignment statements but I feel like this barely passes for what the professor is asking for, here's the statement: slt $t2, $t0, $t1 #t2 holds y = 1 if i < x. It just doesn't really fit with the code at all, it doesn't serve a purpose I feel like it should be involved with the for-loop, any advice?

Here's the basic for-loop the assembly represents:

for (i=0; i<x; i  ) 
   y = y * 2; 

Here's the assembly code in MIPS 32:

.text
.globl main
main:
    li $t1, 7          #test val num of iterations, x = 7
    li $t0, 0          #t0 is our counter i = 0
    #li $t2, 1         #another way to assign y = 1
    slt $t2, $t0, $t1  #t2 holds y = 1 if i < x
    
loop:
    beq $t0, $t1, end  #if (i)t0 == (x)7 end loop
    add $t2, $t2, $t2  #body, y = y * 2
    addi $t0, $t0, 1   #add 1 to i, t0
    j loop             #jump back to the top
end:
    li $v0, 10
    syscall

CodePudding user response:

You are right, the slt is not serving the purpose of loop control since it is not involved in the loop.

The condition i<x is a dynamic condition as part of the iteration of loop, because i changes each iteration.

You might have noticed this deficiency had you single stepped to debug it.

But one problem is that you're not working with great pseudo code as y is never initialized.  We could still work with this but let's note that you have chosen to initialize y in some way that is not part of the given pseudo code.

What you have written in assembly language has equivalent pseudo code of:

y = i < x;              // bad: outside the loop and modifying y
for (i=0; i!=x; i  )    // bad: using condition i!=x
    y = y   y;          // good: valid for y = y * 2;

Can you see the several ways that this pseudo code is not the same as the original?  y is initialized to something not in that original, and the loop exit condition, i!=x is different from that original.  This pseudo code is not logically equivalent and will not run the same as the original.


Let's work from more fundamental principles and logical transformations, so you can see some of the issues:

for (i=0; i<x; i  ) 
   y = y * 2; 

We first convert this for-loop into an equivalent while-loop, because the while loop is more explicit:

i = 0;
while ( i < x ) {
    y = y * 2;
    i  ;
}

Next, we convert this while-loop into the if-goto-label style of assembly language, again, because this is more explicit and each such step gets us closer to assembly language.  You will really start to see what is in the loop and what isn't, even though this is still pseudo code (fyi, this if-goto-label is allowed in C).

    i = 0;
loop1:
    if ( ! (i < x) ) goto loop1Done;  // Exit loop when i < x is false
    y = y * 2;
    i  ;
    goto loop1;
loop1Done:

The first thing to note is that in the if-goto-label style of assembly language, if we want the program to do something else we use an if-goto.  Hopefully you can see that as a consequence of the semantics of if-goto, the natural operation is to tell the processor when to exit the loop — rather than when to stay in the loop as is done in C — and hence the negation of the condition (which can be handled several ways by MIPS).

Next, we can clearly see that the relational operation i < x (and its negation) are required inside the loop, and as such must be repeated each iteration of the loop.

The operation if ( ! (i < x) ) goto ... is legal C code, though can be restated more in pseudo code as: if ( i < x is false ) goto ....

The slt can be used as you describe with operands i in $t0 and x in $t1, so that part was good, but the result need to go to a new temporary register, instead of clobbering the original value y (that was unspecified in the orignal pseudo code).  Let's imagine using $t10 as this alternative temporary.  So, slt $t10, $t0, $t1, and note the placement of it inside the loop.

Now to test the conditional branch part of the condition test.  We want to test that the result of the i<x comparison is false, and branch to exit the loop when so.  Such a branch needs to test $t10 since that holds the result of i<x from slt, and to test that this boolean is false, we would use beq $t10 $0 loop1Done, which says if $t10 is equal to false ($0 is always false) then do the goto/branch that exits the loop.

Left as an exercise for the reader is the completion of the logical transformation from if-goto-label pseudo/C code into assembly code.


Also note from the above discussion that your original pseudo code does not stand alone: an initialization of y is necessary, so in order to actually run this MIPS translation code, you'd would have to add such initialization (if the register for y just happened to be 0 as a simulator would initialize it, then the loop would be most meaningless since y = 0 * 2 would do nothing different, repeatedly).

CodePudding user response:

So to summarize the comments this slt and beq combo was what was needed:

main:
    li $t1, 7          #test val num of iterations, x = 7
    li $t0, 0          #t0 is our counter i = 0
    li $t2, 1          #another way to assign y = 1
    
loop:
    slt $t5, $t0, $t1  #t5 = 1 if i < x
    beq $t5, $0, end   #if t5 != 1 end loop
    add $t2, $t2, $t2  #body, y = y * 2
    addi $t0, $t0, 1   #add 1 to i, t0
    j loop             #jump back to the top
end:
    li $v0, 10         #10 is exit code
    syscall
  • Related