问题描述
.data
org_str: .space 256
rev_str: .space 256
str: .asciiz "Enter the Line: "
pal: .asciiz "palindrome"
not_pali: .asciiz "Not palindrome"
.text
.globl main
main:
li $v0,4
la $a0,str
syscall
# Taking String from the user
li $v0,8
la $a0,org_str
li $a1,256
syscall
# Initilize $t0 and $t2
li $t0,0
li $t1,0
loop_len:
add $t1,$a0,$t0
lb $t2,0($t1) # Load the data in the byte in $t2
beqz $t2,len_exit # Loop till $t2 reaches zero
addiu $t0,$t0,1 # increment of the counter
j loop_len
len_exit:
#Return $t0 to the last Charater
subi $t0,1
li $s0,0 # Initialize variable
addi $s0,0 # Save the length of the String
# Load the original string in $t2
la $t2,org_str
# Intialize i and j
li $t1,0 # i
li $t3,0 # j
reverse_loop:
add $t3,$t2,$t0 # $t2 is the base address
lb $t4,0($t3) # load a byte
beqz $t4,exit # go to the exit if null was found
sb $t4,rev_str($t1) # Overwrite the byte
addi $t0,-1 # decrement of j by 1 (j--)
addi $t1,$t1,1 # increment of i by one (i++)
j reverse_loop # Loop until we reach the length of the String
exit:
li $t0,0
li $t4,0
li $t7,0
CheckChar_loop:
lb $t4,org_str($t0)
lb $t7,rev_str($t0)
beq $t4,$zero,exit_1 # go to the exit if null was found
bne $t4,$t7,not_pal # if $t7 and $t4 not equal
addi $t0,1 # increment of i by 1 (i++)
j CheckChar_loop
exit_1:
#li $v0,1
#addi $a0,0
#syscall
li $v0,pal
syscall
#Exit the program
li $v0,10
syscall
not_pal:
#li $v0,0
#syscall
li $v0,not_pali
syscall
#Exit the program
li $v0,10
syscall
.end main
我正在尝试检查回文。因此,我们的想法是反转字符串并在每个索引处检查反转字符串中的字符是否与原始字符串相同。 我试图检查 org_str 是否等于 rev_str 但它每次都以 $t7 和 $t4 的形式存在,即使它们相等。 rev_str 是 org_str 的反转字符串。
解决方法
基本调试技巧
任何编写汇编语言的人都应该能够单步执行并观察/验证他们的代码执行。
单步执行并验证每条指令是否符合您的预期。大多数指令都有一个主要作用:改变寄存器的值,或改变内存的值。并且所有指令都告诉处理器接下来要运行什么指令。所以,我们需要验证主效果和控制流程(接下来是什么指令)。 (syscall
可以更改多个内存位置并提供返回结果。)
在调试从未经过测试的新代码时,请使用尽可能小的输入来简化调试。
例如,测试输入“A”(0x41)。 (从技术上讲,最小的输入是空字符串,最好也测试一下。)
随着程序的发展,使用断点跳过您已经知道正在运行的代码,然后从那里单步执行新代码。
在你的程序中,你应该已经注意到副本的第一个字节是错误的,甚至在它存储到内存之前,你可以通过单步执行大约 35 条指令来看到这一点。
-
你有一个经典的错误,这是由读取字符串系统调用附加到用户输入文本的换行符引起的。在读取字符串系统调用后检查
org_str
的内存,您应该已经看到了这一点。这个换行符会在代码中的两个地方引起一个差错——在复制循环和 pal 检查循环。您可以使循环基于计数,也可以使用空字节粉碎换行符以缩短该字符的输入。 -
您计算字符数,然后向后复制字符,但错误地依赖 org_str 之前的空字节来停止复制循环。
我们只使用空终止字符串,不应期望字符串以空开始和以空终止——除非明确提供了空初学者(在您的情况下不是这样)。一般来说,在处理字符串(作为参数传递,由其他代码创建)时,我们不能依赖于能够轻松提供空初学者,因此最好的编程实践是在计数(递减一个)时结束复制循环) 达到零。 (在这里很容易被一个人关闭,所以也用空字符串进行测试(即应该构造为 while 循环,而不是重复直到。)) -
停止将寄存器初始化为零,然后再设置一些其他值。你做的相当于
int s0 = 0; // <--- this initialization is pointless
s0 = t0 - 1; // since s0 is immediately repurposed with a new value here
顺便说一句,您从不使用 s0
,因此即使将其设置为 t0-1
也不会被使用,但是当您修复代码的一对一错误时,情况可能会发生变化。