交换字符串中的每两个字符并修复异常错误

Swapping every two characters in a string and fixing exception error

我遇到异常错误,我不确定原因。我需要一些帮助来修复异常以及如何交换用户输入的字符串中的字符?

输入和输出应如下所示:

输入:Apples

输出:pAlpse

.text
main:

#Prompt user for string
la $a0, promptStr
li $v0, 4
syscall

#Get String
li $v0,8 
    la $a0, buffer 
    li $a1, 20
syscall

move $t0, $a0

#Initialize pointer to start of string (specify register)
la $t0, buffer 

#Get a char from the string (register)
loop:   lb $t1, ($t0)

我在这里得到 Instruction references undefined 我不知道为什么,因为我在类似的问题中使用它来在字符串末尾跳出循环。

这是错误信息

Instruction references undefined symbol at 0x00400058
[0x00400058] 0x11200000  beq , [=11=], 0 [strEnd-0x00400058]; 48: beqz $t1, strEnd 
#IF at end of the string branch to endStr
beqz $t0, strEnd 

#Add 1 to the string pointer
add $t0, 1#Fixed

#get the next char in the string
lb $t2, ($t0)

不知道这段代码对不对。我只需要帮助理解 如何交换字符以及代码的外观。

#Swap the 2 chars by writing them back to the original string
sb $t2, ($t0)
sb $t1, ($t0)

#Add 1 to the string pointer
add $t0, 1 #Fixed

#Jump back to loopStart
j loop

#Display modified string
endStr: la $a0,ans
li $v0, 4
syscall

move $a0,$t2
li $v0, 4
syscall

#Blankline
la $a0, end
li $v0, 4
syscall

#Exit porgram
    li $v0, 10
syscall

.data
buffer: .space 20
promptStr: .asciiz "Input a string : "
blankLine   : .asciiz "\n"

您的错误 beqz $t0, strEnd 是一个拼写错误:您所指的标签是 endStr。错误本身会告诉您这一点,突出显示 [strEnd-0x00400058] 为未定义。此外,spim 在加载时警告我:

The following symbols are undefined:
end
ans

修复丢失的标签后,逻辑不太正确,尽管看起来您的方向是正确的。这个想法是在字符对中跨过字符串,交换元素并在遇到空字符时退出(并且,可选地,换行取决于你想如何处理that--stripping/chomping它可能是最好的)。

对于初学者和一个相当次要的问题,在程序顶部附近有一条死指令:

move $t0, $a0  # $t0 will be overwritten by the next la

#Initialize pointer to start of string (specify register)
la $t0, buffer

进入循环和主逻辑,代码beqz $t0, strEnd使用永远不会为0的字符串地址作为分支条件,而不是该地址处的字节$t1。这给出了一个无限循环。

接下来,遍历字符串的指针 $t0 有问题。逻辑

sb $t2, ($t0)
sb $t1, ($t0)

不起作用,因为 $t0 已经递增,所以代码在

之后失去对前一个字节地址的跟踪
#Add 1 to the string pointer
add $t0, 1#Fixed

一种解决方案是在任何 add [=25=], 1 操作之前将 $t0 存储在临时寄存器中。类似于:

move $t3 $t0    # save the address of buf for swap

# ... later on, after incrementing `$t0` ...

sb $t2, ($t3)
sb $t1, ($t0)

您还可以在此处通过 adding/subtracting 偏移量或使用索引遍历字符串来使用索引策略。

最后,我不确定在打印时 move $a0,$t2 在程序结束时应该做什么。

这是解决这些问题并通常清理逻辑的一种可能的解决方案:

.text
main:
    # prompt user for string
    la $a0 prompt
    li $v0 4
    syscall

    # get string
    la $a0 buffer 
    li $a1 20
    li $v0 8
    syscall

    move $s0 $a0    # incrementable pointer to buf

loop:
    # t1 = *(buf++) and exit if '[=15=]' or '\n'
    move $t0 $s0    # save the address of buf for swap
    lb $t1 ($t0)    # t1 = *buf
    beqz $t1 end    # break if '[=15=]'
    beq $t1 10 end  # break if '\n'
    add $s0 1       # buf++

    # t2 = *buf and exit if '[=15=]' or '\n'
    lb $t2 ($s0)    # t2 = *buf
    beqz $t2 end    # break if '[=15=]'
    beq $t2 10 end  # break if '\n'

    # swap the chars
    sb $t2 ($t0)    # *prev_buf = curr_buff_char
    sb $t1 ($s0)    # *buf = prev_buff_char

    # increment pointer and continue to the next pair
    add $s0 1       # buf++
    j loop

end: 
    # display modified string
    la $a0 buffer
    li $v0 4
    syscall
    
    # exit program
    li $v0 10
    syscall

.data
buffer: .space 20
prompt: .asciiz "Input a string : "

样本运行:

$ spim -f swap_alternating_chars.s
Input a string : Apple
pAlpe
$ spim -f swap_alternating_chars.s
Input a string : Apples
pAlpse