【问题标题】:First byte of string ends up unexpectedly being null字符串的第一个字节意外地为空
【发布时间】:2020-04-14 16:29:50
【问题描述】:

我写了以下代码来计算字符串的长度:

strlen:
   # PROLOGUE
    subu $sp, $sp, 8
    sw $ra, 8($sp)
    sw $fp, 4($sp)
    addu $fp, $sp, 8

   # BODY
    #string stored at a0 at the start
    li $v0, 4
    syscall #print string

    li $v0, 0 #starts counter over

    andi $a2, $a0, 0xff    #obtain first byte
    j while

while:
    beqz $a2, ret #exit if null byte encountered
    srl $a0, $a0, 8 #shift to next byte
    andi $a2, $a0, 0xff #obtain first byte again
    add $v0, $v0, 1 #increment counter to be returned
    j while

ret:
    # EPILOGUE
    move $sp, $fp
    lw $ra, ($fp)
    lw $fp, -4($sp)
    jr $ra

它的工作原理是逐字节遍历字符串并递增 v0 直到遇到空字节,然后控制转移到标签 ret 并且程序结束。但是,我的函数似乎总是返回 0,这意味着 v0 永远不会递增,这意味着 a2 在 while 循环开始时为 0。为什么会这样?我已经通过打印系统调用验证了输入字符串实际上是 a0 包含的字符串。

【问题讨论】:

  • 我希望在此函数中看到 lblbu,但似乎没有。 andi 不会从内存中加载任何内容。

标签: assembly mips


【解决方案1】:

这对我有用:

去掉srl命令并替换

andi $a2, $a0, 0xff #obtain first byte again

addu $a2, $a0, $v0
lbu  $a2, ($a2)

在进行地址数学运算后加载 a0 的字节 v0。

只需在调用 addu 之前增加 v0。

【讨论】:

  • 这更没有意义。在我认为您在寄存器中循环超过 4 个字节的字符串数据之前(而不是接受指针 arg)。现在您想将来自 v0 的整数添加到该字符串数据或指针,但仍不添加 lb 吗?
  • @PeterCordes 我不需要加载任何内容,因为字符串在开始时包含在 a0 中。将 a0 视为 char 数组,addu 执行移动 a2 = a0[v0],这正是我想要的。
  • 如果a0 是指向起点的指针addu 会为您提供a2 = &a0[v0]。如果它是 4 个连续字节的字符串数据(就像你做了 memcpy(int_var, string, 4) 一样),它只会修改其中一个字节。 addu 确实 访问内存,并且它不会将更高的字节移动到寄存器的底部。如果在您测试时这有效,您确定没有lb $a2, ($a2) next 吗?
  • @PeterCordes 你是对的。我使用了 lbu,但在发这篇文章时我没有注意到。为确保没有其他我忘记提及的内容,我编辑了主帖以及我的代码现在的样子。
  • 将答案发布为答案,而不是对问题的编辑。我修正了你的答案,至少通过包括负载来回答这个问题。这就是我第一条评论的重点。
猜你喜欢
  • 1970-01-01
  • 2022-01-15
  • 2021-04-15
  • 1970-01-01
  • 2016-03-29
  • 2020-01-13
  • 2022-01-19
  • 2017-08-03
  • 1970-01-01
相关资源
最近更新 更多