alex22666
alex22666

Reputation: 3

Explaining a section of assembly MIPS code?

We recently wrote this code in class. I went through and adding comments that explain to myself how it works. I just don't get how the loop counts the number of chars/spaces in the string. Could someone translate it to me?

#Comment

.data

Str:.asciiz "hello worlds"

prompt:.asciiz "The given string is: "

ans:.asciiz "\n The number of chr and spaces is = "

.text



.globl main

main:

la $a0, prompt #load string prompt into register a0

li $v0, 4 #print string commmand(prints the prompt)

syscall #executes the command


la $a0, Str #loads Str into a0 

li $v0, 4 #print string commnad

syscall #executes the command


li $t0, 0 #set t0 to 0

la $t1, Str #load Str into register t1


Loop1: #begins the loop SECTION I DONT UNDERSTAND

lb $t2, 0($t1) #loads byte into t2?

beqz $t2, Tim #if t2 == to zero go to Tim ?

addi$t0,$t0,1 #incremet t0 by 1 ?

addi$t1,$t1,1 #initialize t1 to 1 ?

j Loop1

syscall #executes the loop


Tim:
la$a0,ans #load ans into a0

li$v0,4 #print ans string

syscall #executes command


move$a0,$t0 #move t0 to a0

li$v0,1 #print int

syscall #execute command

Upvotes: 0

Views: 189

Answers (2)

Erik Eidt
Erik Eidt

Reputation: 26646

This code is counting bytes in a null-terminated C-style string.

Let's translate this to C to see what it is doing, here we're using the if-goto style mimicking assembly's flow of control.

Loop1:
  int ch = *ptr;
  if ( ch == 0 ) goto Tim;      // ch is $t2
  counter++;                    // counter is $t0
  ptr++;                        // ptr is $t1
  goto Loop1;

And if we translate that to structured programming we get:

while ( *ptr != '\0' ) { ptr++; counter++; }

Make sense?


As an aside, the syscall just after the loop does not have any of the normal syscall setup, so appears suspicious; however, to be clear, it is dead code — code located in between an unconditional jump and the next label is (almost) certainly unreachable by any flow of control of the program (we call that dead code; it should be removed — and the comment is erroneous).


Using $t0 — a calling convention volatile (scratch) register — to hold the counter live across a print-style syscall is also suspicious.  Sometimes this will work but in other environments, not.  It would be more proper to use a callee-saves (preserved/non-volatile) register like $s0, or a memory location rather than relying on $t0 to be unchanged.

Upvotes: 0

mangusta
mangusta

Reputation: 3544

Let's go from the very beginning (skipping 2 syscalls before the loop):

The analyzed string is hello worlds located at address Str

t0 will contain the number of characters in hello worlds. This is what we need to find and print. It is initialized by zero:
li $t0, 0

t1 contains the address of the character currently processed. It is initialized by Str which is the address of hello worlds and at the same time it is the address of its first character h:
la $t1, Str

The loop begins:

iteration1:

Currently processed character is loaded into t2:
lb $t2, 0($t1)
Recall that lb reg, offset(addr) implies loading 1-byte value at address addr + offset into register reg. In our case, it implies loading 1-byte value at address t1 + 0 into t2. t1 + 0 is the address of current character i.e. h. Hence h is loaded into t2

beqz $t2, Tim implies jumping to label Tim in case if t2 is zero. but t2 has value h so it is not zero. The purpose of this check is to detect the null-terminator which denotes the end of string. As soon as we detect that null-terminator, we are all done and the loop must finish

addi $t0, $t0, 1 - we increment our counter (the number of characters we have processed so far). t0 becomes 1

addi $t1, $t1, 1 - we increment the address of the character currently processed. In other words we move on to the next character of the string (we increment it by 1 because character size is 1 byte). Now t1 has the address of the second character which is e

j Loop1 - we start a new iteration

iteration 2:

lb $t2, 0($t1) - e is loaded into t2
beqz $t2, Tim - e is not zero so we don't jump to Tim and continue the loop
addi $t0, $t0, 1 - t0 becomes 2
addi $t1, $t1, 1 - t1 contains the address of third character which is l
j Loop1 - start new iteration

and so on until beqz $t2, Tim checks that t2 contains zero, in which case the program stops the loop and jumps to Tim

Upvotes: 1

Related Questions