需要帮助在MIPS中搜索句子中的单词

时间:2017-03-08 18:27:56

标签: assembly mips sentence

我希望你们都过得愉快。我希望我可以通过我的项目代码获得一些帮助。基本上是一个句子" FADED IN FADED OUT。"在提示时键入,然后搜索单词" FADED"键入并执行代码以查看单词" FADED"在句子中,如果是,它会说" x匹配发现"如果没有"找不到匹配"。好吧,当我编译并运行时,它给我一个"第65行:0x00400098处的运行时异常:地址超出范围0x00000000"错误,有多行有此错误。有人能帮我这个吗?过去3天我一直在尝试这样做,最后打破了一些帮助...如果您有任何疑问,请告诉我!

.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

1 个答案:

答案 0 :(得分:1)

你的地方有一些很好的结构。

但是,在很多地方评论与代码不匹配(例如,你正在做一堆cut-n-paste)。而且,虽然我意识到你刚刚开始,但很多你的侧栏评论只是反刍了asm指令。 (例如):

addi $s4, $s4, 1    # add one to s4 to move to next character

如果评论遵循算法,那将有助于您理解:

addi $s4, $s4, 1    # point to next character

另一个问题是checkloop:实际上应该包含循环而不是固定数量的bne个。

除了顶部评论块中其他人提到的一些问题之外,一个重要的问题是您正在重置句子/字符串指针。你真正需要的是另一个指针[加1],它会在句子中记住“你离开的地方”并从那里重新开始内循环(即checkloop:

虽然我尽可能多地保留你的代码,但我不得不重构它。我使用的一个“技巧”是创建一个提示用户,读取缓冲区,然后将句点和换行符转换为空格的函数[这使得扫描循环更加容易]

无论如何,这是[请原谅无偿的风格清理]:

    .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