需要帮助搜索在MIPS中的句子中的单词
问题描述:
我希望你们都有美好的一天。我希望我能得到我的项目代码的一些帮助。基本上是一句“渐行渐远”。在提示时键入,然后键入搜索词“FADED”,执行代码以查看单词“FADED”是否在句子中,如果是,则表示“找到匹配”并且if不是“找不到匹配”。那么当我编译并运行它给我一个“行65:运行时异常在0x00400098:地址超出范围0x00000000”错误,并且有多条线路有此错误。任何人都可以帮助我吗?过去3天我一直试图做,最后得到一些帮助......如果您有任何问题,请让我知道!需要帮助搜索在MIPS中的句子中的单词
.data
str: .space 100 # Pre Allocate space for the input sentence
input: .space 30 # Pre Allocate space for the input sentence
ins: .asciiz "Please enter a sentence: " # string to print sentence
seek: .asciiz "Please enter a word: " # string to print sentence
nomatch: .asciiz "No Match(es) Found"
found: .asciiz " Match(es) Found"
newline: .asciiz "\n" # string to print newline
.text
li $v0, 4 # syscall to print string
la $a0, ins # move str into a0
syscall # syscall
li $a1, 100 # allocate space for the string
la $a0, str # load address of the input string
li, $v0, 8 # read string input from user
syscall # issue a system call
move $t9, $a0 # move string to t5
li $v0, 4 # syscall to print string
la $a0, seek # move str into a0
syscall # syscall
la $a0, input # load address of the input string
li $a2, 30 # allocate space for the string
li, $v0, 8 # read string input from user
syscall # issue a system call
move $t8, $a0 # move string to t8
la $s5, input # create space for the input word we are looking for in s5
wloop: # loop to allocate space for the word we are looking for to a register
lb $t0, 0($t8) # load first character into t0
beqz $t0, sentence # branch to sentence loop if null character
sb $t0, 0($s5) # store the current character into current address of s5
addi $t8, $t8, 1 # add one to t8 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to the next allocated space
j wloop # jump back to wloop
la $s4, str # create space for the input sentence
sentence: # loop to allocate space for the word we are looking for into a register
lb $t0, 0($t9) # load first character into t0
beqz $t0, resetsen # branch to check loop if null character
sb $t9, 0($s4) # store the current character into current address of s4
addi $t9, $t9, 1 # add one to t9 to move to next character
addi $s4, $s4, 1 # add one to s5 to move to the next allocated space
j sentence # jump back to sentence
resetsen:
li $s4, 0 # reset sentence back to 0 (first character)
resetword:
li $s5, 0 # reset word we are looking for back to 0 (first character)
check:
lb $t1, 0($s4) # load current character of sentence to t1
beq $t1, 46, quit # branch to QUIT if period found
bne $t1, 70, nextword # if t1 != t0 branch to nextword
beq $t1, 70, checkword # branch to found if t1 = f
nextword: # loop to get to the next word
lb $t1, 0($s4) # load current character to t1
beq $t1, 46, quit # branch to quit if period found
bne $t1, 32, increment # if current character is not a spaace branch to increment
beq $t1, 32, plusone # if current character is a space branch to plusone
increment: # increment procedure
addi $s4, $s4, 1 # add one to s4 to move to next character
j nextword # jump to nextword
plusone: # plusone procedure
addi $s4, $s4, 1 # add one to s4 to move to next character
j resetword # jump to check
checkword:
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for a)
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for d)
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for e)
addi $s4, $s4, 1 # add one to s4 to move to next character
addi $s5, $s5, 1 # add one to s5 to move to next character
lb $t1, 0($s4) # load current character of sentence to t1
lb $t0, 0($s5) # load current character of sentence to t0
bne $t1, $t0, increment # if t0 != t1 branch to increment (looking for d)
addi $t2, $t2, 1 # add one to t2 which counts occurences
j resetword
quit:
beqz $t2, exit # if t2 = 0 branch to exit
li $v0, 1 # syscall to print integer
move $a0, $t2 # move str into a0
syscall # syscall
li $v0, 4 # syscall to print string
la $a0, found # move found into a0
syscall # syscall
j endprogram
exit:
li $v0, 4 # syscall to print string
la $a0, nomatch # move nomatch into a0
syscall # syscall
endprogram:
li $v0, 10
syscall
答
你在地方有一些很好的结构。
但是,在许多地方,评论与代码不匹配(例如,您正在做一堆剪切粘贴)。而且,虽然我意识到你刚刚开始,但很多侧边栏评论只是回顾了asm指令。 (EG):
addi $s4, $s4, 1 # add one to s4 to move to next character
这将有助于你与你的理解,如果意见跟着算法:
addi $s4, $s4, 1 # point to next character
另一个问题是,checkloop:
实际上应该包含一个循环,而不是bne
insts对于固定数量。
除了顶部注释块中其他人提到的一些问题之外,其中一个重要问题是您要重置句子/字符串指针。你真正需要的是另一个指针[增加1],可以记住句子中“停止的位置”,然后重新启动内部循环(即checkloop:
)
尽管我试图保留尽可能多的代码,可能,我不得不重构一下。我使用的一个“技巧”是创建一个函数,提示用户,读取缓冲区,然后将句号和换行符转换为空格[这使得扫描循环变得更容易]
无论如何,这里是[please pardon无偿款式清理]:
.data
str: .space 100 # space for sentence
input: .space 30 # space for word to scan for
ins: .asciiz "Please enter a sentence: "
seek: .asciiz "Please enter a word: "
nomatch: .asciiz "No Match(es) Found"
found: .asciiz " Match(es) Found"
newline: .asciiz "\n"
quo1: .asciiz "'"
quo2: .asciiz "'\n"
.text
.globl main
# registers:
# t0 -- current char from string
# t1 -- current char from word
# t4 -- space char
# t5 -- pointer to current char in word to scan for
# t6 -- pointer to current char in string for given pass
# t7 -- pointer to start of scan in string ("where we left off")
# t8 -- word match count
main:
# read sentence
la $a0,ins # prompt
la $a1,100 # length of buffer
la $a2,str # buffer address
jal rdstr
# read scan word
la $a0,seek # prompt
la $a1,30 # length of buffer
la $a2,input # buffer address
jal rdstr
la $t7,str # pointer to first char in string
li $t8,0 # zero the match count
strloop:
move $t6,$t7 # start scan where we left off in string
la $t5,input # start of word to scan for
li $t4,0x20 # get ascii space
wordloop:
lbu $t0,0($t6) # get char from string
addiu $t6,$t6,1 # advance pointer within string
lbu $t1,0($t5) # get char from scan word
addiu $t5,$t5,1 # advance pointer within scan word
bne $t0,$t1,wordfail # char mismatch? if yes, fly
bne $t1,$t4,wordloop # at end of scan word? if no, loop
addi $t8,$t8,1 # increment match count
wordfail:
addiu $t7,$t7,1 # advance starting point within string
lbu $t0,0($t7) # get next char in sentence
bnez $t0,strloop # end of sentence? if no, loop
beqz $t8,exit # any match? if no, fly
li $v0,1 # syscall to print integer
move $a0,$t8 # print match count
syscall
li $v0,4 # syscall to print string
la $a0,found # move found into a0
syscall
j endprogram
exit:
li $v0,4 # syscall to print string
la $a0,nomatch # move nomatch into a0
syscall
endprogram:
li $v0,10
syscall
# rdstr -- read in and clean up string (convert '.' and newline to space)
#
# arguments:
# a0 -- prompt string
# a1 -- buffer length
# a2 -- buffer address
#
# registers:
# t0 -- current character
# t1 -- newline char
# t2 -- ascii period
# t3 -- ascii space
rdstr:
# prompt user
li $v0,4 # syscall to print string
syscall
# get the string
move $a0,$a2 # get buffer address
li $v0,8 # read string input from user
syscall # issue a system call
li $t1,0x0A # get ascii newline
li $t2,0x2E # get ascii dot
li $t3,0x20 # get ascii space
# clean up the string so the matching will be easier/simpler
rdstr_loop:
lbu $t0,0($a0) # get character
beq $t0,$t1,rdstr_nl # fly if char is newline
beq $t0,$t2,rdstr_dot # fly if char is '.'
rdstr_next:
addiu $a0,$a0,1 # advance to next character
j rdstr_loop
rdstr_dot:
sb $t0,0($a0) # replace dot with space
j rdstr_loop
rdstr_nl:
sb $t3,0($a0) # replace newline with space
j rdstr_done # comment this out to get debug print
# debug print the cleaned up string
li $v0,4 # output string
la $a0,quo1 # output a quote
syscall
move $a0,$a2 # output the cleaned up string
syscall
la $a0,quo2
syscall
rdstr_done:
jr $ra # return
哪条线是65线?据推测它使用了一个糟糕的指针。反过来看看为什么那个指针没有正确的值。另外,使用调试器单步执行代码。 – Jester
不太可能。更可能的是'lb $ t1,0($ s4)#将句子的当前字符加载到t1',因为你在那里使用'$ s4'作为指针,但是你早先将它清零:'li $ s4,0#将句子重置为0(第一个字符)'。你可能想要'la $ s4,str'来代替。 – Jester
使用调试器单步执行代码并查看它不在您想要的位置。 – Jester