Strlen 子例程 (MIPS)

Strlen subroutine (MIPS)

我正在尝试用 MIPS 编写一个 strlen 子例程。 当字符串在内存中时该函数有效,但如果字符串是用户输入的,则答案始终为 = (correct_value + 1)。 例如:

String: Hello
Length: 6

为什么它不适用于输入?这是我的代码。我正在使用 MARS。

    .data
str1:   .asciiz String: "
strTest:.space 20
str2:   .asciiz "Length: "
    .text
    .globl main

main:  
    addiu   $sp, $sp, -4            # save space
    sw      $ra, 0($sp)             # push $ra

    la      $a0, str1               # print(str1)
    li      $v0, 4
    syscall

    li      $a1, 20                 # read strTes
    la      $a0, strTest
    li      $v0, 8
    syscall


    jal     strlen                  # call strlen

    move    $t0, $v0                # save result to $t0

    la      $a0, str2               # print str2
    li      $v0, 4
    syscall

    move    $a0, $t0                # print result
    li      $v0, 1
    syscall

    lw      $ra, 0($sp)             # restore $ra
    addiu   $sp, $sp, 4             # restore $sp
    jr      $ra


strlen:
    li      $v0, 0                  # len = 0

while:  lb      $t0, ($a0)              # get char
    beqz    $t0, wh_end             # if(char == '[=11=]') --> end while
    addi    $v0, $v0, 1             # len++
    addiu   $a0, $a0, 1             # *s++
    j       while
wh_end:
    jr      $ra

我的猜测是 MARS 还包括用户输入 his/her 字符串后按下的 enter/return。您的代码看起来不错,因此最合乎逻辑的是 MARS returns "hello\n" 而不是 "hello",就像您希望的那样。

要解决此问题,您可以像对 "[=13=]" 那样添加检查,然后再对 "\n" 进行检查。我不确定它是否会起作用,但你可以尝试添加

subi $t1, $t0, 10
beqz $t1, wh_end

beqz $t0, wh_end 之后。这是可行的,因为 \n 终止字符的 ASCII 值为 10,因此如果从 $t0 中减去 10,并以 0 结尾,则您有一个终止字符。

祝你好运!