2017-03-08 61 views
2

我希望你們都有美好的一天。我希望我能得到我的項目代碼的一些幫助。基本上是一句「漸行漸遠」。在提示時鍵入,然後鍵入搜索詞「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 
+0

哪條線是65線?據推測它使用了一個糟糕的指針。反過來看看爲什麼那個指針沒有正確的值。另外,使用調試器單步執行代碼。 – Jester

+0

不太可能。更可能的是'lb $ t1,0($ s4)#將句子的當前字符加載到t1',因爲你在那裏使用'$ s4'作爲指針,但是你早先將它清零:'li $ s4,0#將句子重置爲0(第一個字符)'。你可能想要'la $ s4,str'來代替。 – Jester

+0

使用調試器單步執行代碼並查看它不在您想要的位置。 – Jester

回答

1

你在地方有一些很好的結構。

但是,在許多地方,評論與代碼不匹配(例如,您正在做一堆剪切粘貼)。而且,雖然我意識到你剛剛開始,但很多側邊欄評論只是回顧了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