我想实现多词支持。
例如abc AAAA cbAAaa => 000 4444 222222
目前该程序所做的只是第一个单词转换。
从火星模拟器中的调试器看来,它正确地执行了所有循环。寄存器值相同。 (也许我错过了什么) 我认为单词的长度必须少于10个字符。
如果有人发现错误,我将不胜感激。 另外,如果您有调试技巧或代码改进的任何技巧,请随时说。
我的代码:
.data
prompt: .asciiz "Enter a string: "
msgout: .asciiz "Output string: "
input: .space 256
output: .space 256
.text
.globl main
main:
li $v0, 4 # Print enter a string prompt
la $a0, prompt
syscall
li $v0, 8 # Ask the user for the string they want to reverse
la $a0, input # We'll store it in 'input'
li $a1, 256 # Only 256 chars/bytes allowed
syscall
la $t2, ($a0) # t2 - input string
word:
li $t1, 0 # Normal counter
li $t5, 0 # Uppercase counter
li $t6, 0 # First letter of word
j word_countUppercase
word_precountUppercase:
addi $t1, $t1, 1 # Add 1 to index to avoid space in next word
la $t6, ($t1) # Set t6 to the first index of t2 (start of word)
la $t5, 0 # $t5 - 0
word_countUppercase:
#addi $t1, $t1, $t7
add $t3, $t2, $t1 # $t2 is the base address for our 'input' array, add loop index
lb $t4, 0($t3) # load a byte at a time according to counter
beq $t4, ' ', word_prereplace # We found end of word
bltu $t4, ' ', word_prereplace # We found end of string
addi $t1, $t1, 1 # Advance our counter (i++)
bltu $t4, 'A', word_countUppercase
bgtu $t4, 'Z', word_countUppercase
addi $t5, $t5, 1 # Advance our counter (i++)
j word_countUppercase
word_prereplace:
la $t2, ($a0) # t2 - input string
la $t1, ($t6) # Normal counter
addi $t5, $t5, '0'
word_replace:
add $t3, $t2, $t1 # $t2 is the base address for our 'input' array, add loop index
lb $t4, 0($t3) # load a byte at a time according to counter
beq $t4, ' ', word_replaceExit # end of the word
bltu $t4, ' ', exit # We found end of string
sb $t5, output($t1) # Overwrite this byte address in memory
addi $t1, $t1, 1 # Advance our counter (i++)
j word_replace
word_replaceExit:
j word_precountUppercase
exit:
li $v0, 4 # Print msgout
la $a0, msgout
syscall
li $v0, 4 # Print the output string!
la $a0, output
syscall
li $v0, 10 # exit()
syscall
答案 0 :(得分:2)
我的输出中有空格,因此字符串为:111 [] 222 [] 1111,而print则将其打印到第一个空格,因此只有111。
要解决此问题,我添加了以下代码:(在单词标签之前)
li $t1, 0 # Normal counter
rewriteoutput:
add $t3, $t2, $t1 # $t2 is the base address for our 'input' array, add loop index
lb $t4, 0($t3) # load a byte at a time according to counter
bltu $t4, ' ', word # We found end of string
sb $t4, output($t1) # Overwrite this byte address in memory
addi $t1, $t1, 1 # Advance our counter (i++)
j rewriteoutput
我知道我们可能可以做得更好,但是不明白为什么我做不到
sw $a0, output
代替它(运行时错误:运行时异常在0x0040002c:存储地址未在字边界0x10010121上对齐)
答案 1 :(得分:2)
编辑:原始问题的答案是,原始代码仅填充了与单词内容相对应的字节的输出缓冲区,但保留了未定义的内存,这在MARS模拟器中恰好为零,因此意外出现了零终止符在第一个单词之后,并且MARS的“打印字符串”服务确实期望以零结尾的字符串=仅打印了第一个单词。
这是我针对同一任务的变体,它使用各种快捷方式以(少量)指令(几乎仍然是O(N)复杂性)来完成相同的事情。
我也以确保多个空格,以空格开头/结尾或空输入的输入正确工作的方式编写了它(对于输入中的“两个空格”,它也将输出“两个空格”)(我没有用您的原始代码测试所有这些,所以我并不是说有一些错误,似乎应该可以很好地处理它们,我只是对我的变体进行了彻底的测试):
# delayed branching should be OFF
.data
prompt: .asciiz "Enter a string: "
msgout: .asciiz "Output string: "
input: .space 256
output: .space 256
.text
.globl main
main:
li $v0, 4 # Print enter a string prompt
la $a0, prompt
syscall
li $v0, 8 # Ask the user for the string they want to reverse
la $a0, input # We'll store it in 'input'
li $a1, 256 # Only 256 chars/bytes allowed
syscall
la $a1, output
# a0 = input, a1 = output
new_word:
move $t0, $zero # t0 word length = 0
li $t1, '0' # t1 uppercase counter = '0' (ASCII counter)
word_parse_loop:
lbu $t2, ($a0) # next input character
addi $a0, $a0, 1 # advance input pointer
bltu $t2, 33, word_done # end of word detected (space or newline)
# "less than 33" to get shorter code than for "less/equal than 32"
addi $t0, $t0, 1 # ++word length
# check if word character is uppercase letter
addiu $t2, $t2, -65 # subtract 'A' => makes t2 = 0..25 for 'A'..'Z'
sltiu $t3, $t2, 26 # t3 = (t2 < 26) ? 1 : 0
add $t1, $t1, $t3 # ++uppercase counter if uppercase detected
j word_parse_loop
word_output_fill:
# loop to fill output with uppercase-counter (entry is "word_done" below)
sb $t1, ($a1)
addi $a1, $a1, 1
addiu $t0, $t0, -1
word_done:
# t0 = word length, t1 = uppercase ASCII counter, t2 = space, newline or less
# a0 = next word (or beyond data), a1 = output pointer (to be written to)
bnez $t0, word_output_fill
bltu $t2, ' ', it_was_last_word
# t2 == space, move onto next word in input (store space also in output)
sb $t2, ($a1)
addi $a1, $a1, 1
j new_word
it_was_last_word:
# finish output data by storing zero terminator
sb $zero, ($a1)
# output result
li $v0, 4 # Print msgout
la $a0, msgout
syscall
li $v0, 4 # Print the output string!
la $a0, output
syscall
li $v0, 10 # exit()
syscall
注意事项(“技巧”?)
< 26
测试足以检测所有大写字母。或者如果您对代码的特定部分还有其他疑问,请随时提问。