-2

I'm trying to write a function that counts the length of a string with the fewest number of dynamic instructions. This is what I have as of now:

strlen:
    li      $v0, 0                  # len = 0

top:  
    lbu $t0, 0($a0)             # get char
    addi    $v0, $v0, 1             # len++
    addiu   $a0, $a0, 1             # *s++
    bne $t0, $0, top        #if char != '\0', loop
ret:
    addiu   $v0, $v0, -1
    jr      $ra

I'm trying to reduce it with regards to a 10-character string so making it into a recursive function wouldn't be an "improvement". Is it possible to reduce the number of instructions from here at all?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
jiyoon
  • 201
  • 4
  • 14
  • Which instructions are dynamic ones? – Scott Hunter Jul 02 '20 at 15:03
  • @ScottHunter: The "dynamic instruction count" is the number instructions that actually execute, not the number you see in disassembly. The phrasing here is awkward ("dynamic instructions" isn't a thing), but that's the meaning. e.g. things like loop unrolling are possible: larger code size, but fewer instructions actually executed if the trip-count is high. That's the opposite of simplification, though. But if you actually care about strlen performance, see [Why does glibc's strlen need to be so complicated?](//stackoverflow.com/q/57650895) - that word-at-a-time C is used on MIPS. – Peter Cordes Jul 02 '20 at 21:09
  • 1
    *making it into a recursive function wouldn't be an "improvement"* - that's basically never an improvement in asm, for large or small problems, for something you can do with a simple loop! You have to save a whole stack of return addresses. Even if you need to manually implement a stack data structure, that's often more performant, just harder to write correctly. C compilers will even turn C recursion into asm loops whenever they can. – Peter Cordes Jul 02 '20 at 21:14

1 Answers1

3

You don't need to increment a counter in the loop, you can subtract end - start to get the length. For example:

strlen:
    addiu  $v0, $a0, 1   # start + 1

top:  
    lbu    $t0, 0($a0)   # get char
    addiu  $a0, $a0, 1   # s++
    bne    $t0, $0, top  # if char != '\0', loop
ret:
    subu   $v0, $a0, $v0 # (end+1) - (start+1)
    jr     $ra
   
Jester
  • 56,577
  • 4
  • 81
  • 125