我正在尝试反转汇编中的字符串。我是新手,所以我不知道如何调试。这是当前的代码。
## $a0 --> address of string
## $v0 --> string length
reverse_string:
j string_length # this subroutine works
la $t3, STR_str # contains the string
div $t9, $v0, 2 # divide string length by 2
add $t8, $zero, $zero # this is the counter
sub $v0, $v0, 1 # string length - 1
add $t7, $t3, $v0 # offset by string length - 1 to find last character
j reverse_string_loop
reverse_string_loop:
beq $t8, $t9, end_for_all # check if it has reached the halfway point
lb $t1, 0($t7) # load last character into $t1
lb $t2, 0($t3) # load current character into $t2
sb $t1, 0($t3) # store last character at current location
sb $t2, 0($t7) # store current character at last location
add $t3, $t3, 1
sub $t7, $t7, 1
add $t8, $t8, 1
我对 MIPS 中的存储和加载如何工作只有有限的了解,所以我猜问题就是这样。
它应该反转字符串,但目前它没有对测试字符串做任何事情。我没有写主要内容,但如果有帮助的话,这就是它的结构:
### reverse_string
##
li $v0, 4
la $a0, STR_reverse_string
syscall
la $a0, STR_str
jal reverse_string
la $a0, STR_str
jal print_test_string
lw $ra, 0($sp) # POP return address
addi $sp, $sp, 4
jr $ra
当我尝试运行它时弹出这些错误:
PC=0x00000004 处发生异常 读取文本中的错误地址:0x00000005
控制台说一些关于错误指令地址的信息,但我不确定发生在哪里。
您没有正确调用字符串长度。函数调用在汇编中非常复杂。
首先,您必须将字符串长度传递给返回地址。返回地址是一项功能,允许从不同的调用者、调用链的不同级别、甚至从同一调用者的不同调用站点调用同一函数,并且仍然能够返回到正确的调用者。返回地址通常使用
jal
指令传递,该指令将返回地址捕获到 $ra 中,供该函数稍后使用以返回到正确的调用者。我们没有看到返回地址在 C 或汇编之外的其他语言中具体化,但是,几乎所有汇编语言都让您以某种方式处理返回地址的概念。
我们可以在代码中看到您使用的是
j
而不是 jal
。异常中的 PC=0004 是另一个迹象,表明没有好的返回地址传递到字符串长度中。
其次,当跨越调用边界时,应遵守寄存器的使用情况。被调用函数可以使用一些寄存器而无需关注(调用破坏),而其他寄存器则可以使用,但必须将其原始值返回给调用者(调用保留)。相反,调用者不能依赖调用破坏的寄存器来幸存函数调用,但他们可以依赖调用保留的寄存器来幸存。为了使这样的系统发挥作用,所有职能都必须遵守规则。可以针对自定义场景省略/优化这些规则,尽管通常这样做是为了性能,而不一定是为了学习标准调用约定时的课程作业。