簡體   English   中英

為什么我的MIPS程序沒有從內存中加載值?

[英]Why isn't my MIPS program loading values from memory?

我正在開發一個將字符串位置反轉的程序。

但是我遇到了一些麻煩。

該程序通過循環遍歷字符串一次來獲得字符串的長度。

一旦找到另一個循環,就通過將值保存在臨時寄存器中來前后交換字符,然后將另一個值所在的字節存儲到字節中。

然后,字符串開頭的地址遞增,結尾的地址遞減。 完成此操作,直到在循環中也增加的臨時寄存器等於字符串長度的一半。

但是由於某種原因,當我逐步執行程序時,它不會在第二個循環中將字符的值存儲到寄存器中。

有人會為什么會這樣嗎?我該如何解決?

謝謝。

.data
msg:    .asciiz "Hello World"
nline: .asciiz "\n"
.globl main


.text
#t0 address location
#t1 address location used to increment and find \0
#t2 value stored in addres location of t1
#t3 stores length of string
main: 
    la $t0,msg  #load address location

    add $t1,$t0,$zero #loads address location for use in loop
    lb $t2,0($t1)   #loads value found at address in t1 

    add $t3,$zero,$zero #set length to 0


    len: #increments value that determines length and memory location of current character
    addi $t3,$t3,1
    add $t0,$t0,1
    #add $a0,$zero,$t3
    #li $v0,1
    #syscall
    lb $t2,0($t0)

    bne $t2,$zero,len   #loops back to  len if null character is not found


    srl $t4,$t3,1


    add $t5,$t0,$zero
    add $t6,$t3,$t0

    add $t9,$zero,$zero


    swap:
    lb $t7,0($t5)
    lb $t8,0($t6)

    sb $t8,0($t6)
    sb $t7,0($t5)

    addi $t5,$t5,1
    sub $t6,$t6,1
    addi $t9,$t9,1

    bne $t4,$t9,swap


    li $v0,10
    syscall

逐步執行程序時,應驗證所有假設,尤其是在發現一些問題(例如字母值未正確加載)的情況下。

在您的情況下(我確實在MARS中運行過它),就在標簽swap:寄存器包含:

t0  0x1001000b
t1  0x10010000
t2  0
t3  11
t4  5
t5  0x1001000b
t6  0x10010016

msg符號值為0x10010000 那只是在t1 ,但是您使用t5, t6來加載字符串的值, t5指向msg的零終止符, t6已經消失了。 因此, “某些原因”是您沒有讀取想要的內存,而是超出了內存。

從代碼中的注釋來看,您在“ strlen”中使用了t0而不是t1 ,並且您希望t0保留原始msg地址(但是t1保留了它, t0指向msg的零終止符)。

同樣,您的代碼對於空字符串也將失敗,因為您執行了一些初始lb但未對其進行測試,然后從字符串的第二個字節開始檢查零。

總的來說,您可能經常會嘗試清理一下第一個想法,並簡化一些想法,在此特定任務中,您只需使用指向字符串的指針即可完成所有操作,而無需將length / half_length計算為整數:

.data
msg:    .asciiz "Hello World"

.text
.globl main
main: 
    la   $t0,msg        # t0 = string address
    add  $t1,$t0,$zero  # t1 = string address for "strlen"

len: # find zero terminator of string
    lb   $t2,($t1)      # t2 = letter from string 
    addi $t1,$t1,1      # advance string pointer
    bne  $t2,$zero,len  # loop back to len if null character is not found

  # t0 = string address, t1 = points 1 byte after the zero terminator
    addi $t1,$t1,-2     # adjust t1 to point to last character
    # validate that t0 < t1 (will not for empty or one letter strings)
    bgeu $t0,$t1,too_short_to_reverse  # sltu+beq

swap:
    lb   $t2,0($t0)     # swap letters at t0/t1 positions
    lb   $t3,0($t1)
    sb   $t2,0($t1)
    sb   $t3,0($t0)
    addi $t0,$t0,1      # adjust pointers
    addi $t1,$t1,-1
    blt  $t0,$t1,swap   # while t0 < t1 keep swapping letters
too_short_to_reverse:
    # done, string is reversed

    # debug output of string to see it reversed
    li   $v0,4
    la   $a0,msg
    syscall

    li   $v0,10         # exit syscall
    syscall

(使用了很少的偽指令,雖然您的原始源代碼看起來像您在嘗試避免使用它們,但是您仍然有一些不准確的偽指令,這些偽指令必須通過匯編程序進行任何調整,例如add $t0,$t0,1 -> addi

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM