Zannikos Ch
Zannikos Ch

Reputation: 31

while loop with 2 conditions to assembly code

I want to convert a while loop like that:

i=0; 
while ( (s[i]!='t') && (i<=20) ) {
  d[i]=c[i];
  i++;
}

with 2 conditions to assembly code. how can i do that? below is the version with 1 condition in the while.

    #################################################
# lab3_3a.s                 #
# while loop    char!=ASCII 0           #
#################################################
    .text       
        .globl __start 
__start:            # execution starts here

    li $t1,0        # counter for string
    li $s0,'t'      # chararacter to end copy
while:  lbu $t0,string($t1) # load a character
    sb $t0,copy($t1)    # copy character
    beq $t0,$s0,end     # if character to end copy then exit loop
    addi $t1,$t1,1      # increment counter
    b while         # repeat while loop
end:    li $t2,0
    sb $t2,copy($t1)    # append end character to copied string
    la $a0,copy     # display copy
    li $v0,4    
    syscall
    li $v0,10       # exit
    syscall         
        .data
string:     .asciiz "Mary had a little lamb"
copy:       .space 80

thanks guys.

Upvotes: 2

Views: 1612

Answers (2)

Ped7g
Ped7g

Reputation: 16596

i=0; 
while ( (s[i]!='t') && (i<=20) ) {
  d[i]=c[i];
  i++;
}

Would contain two bugs, if s would be defined as char s[20];, first the (i<=20) would be one-too-much. It's very unusual to use <= in array length tests, it may be still correct if char s[21]; is defined, but then you have two different "magic numbers" in source, 20 and 21. And the second bug is, even if you have correct length test, the (s[i]!='t') will execute ahead of i validation, so at the last character you will have out-of-bounds access.

Anyway, that C be written in C in a bit more "assembly-like" way like this:

i=0;
while(true) {  // Your "b while" is doing this already
  if (20 < i) break;    // test length first, to avoid s[21] (out of bounds)
  if ('t' == s[i]) break; // test for "terminator" character
    //^^ Yoda notation, to catch typo like (s[i]='t') as error
  d[i]=c[i];
  ++i;  // pre-increment form is more accurate to your intent
        // As you don't need original value after incrementation
}
// breaks will jump here.

This should be easy to rewrite in assembly, try it...


edit: and your original assembly is not "while", but "do-while", i.e. copy of first byte will execute under all circumstances, which is not what the C example is doing.


edit2: meanwhile of course this assumes you know the boolean logic algebra, as every programmer has to. I.e. you know that:

!(A && B) <=> (!A) || (!B) 

Upvotes: 1

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239714

So, you've already successfully inverted one of the conditions and used it to jump out of the loop. Does it occur to you that you can do the same for the other?

    li $t1,0        # counter for string
    li $s0,'t'      # chararacter to end copy
    li $s1,20       # count to end copy
while:  lbu $t0,string($t1) # load a character
    sb $t0,copy($t1)    # copy character
    beq $t0,$s0,end     # if character to end copy then exit loop
    bgt $t1,$s1,end     # if count exceeds limit then exit loop
    addi $t1,$t1,1      # increment counter
    b while         # repeat while loop

Upvotes: 1

Related Questions