assembly MIPS组件排序

g0czyy6m  于 2022-11-30  发布在  其他
关注(0)|答案(2)|浏览(223)

我的任务是使用MIPS汇编和QTSpim对硬编码的整数数组进行排序和打印。我一直在尝试遵循这里发布的其他类似问题,但我很难理解我现在哪里出错了。我得到“Exception occurred at PC= 0x 00400068 Bad address in data/stack read:0x 10040000”QTSpim高亮显示“[80000180] 0001 d821加27美元,0美元,1美元; 90:移动$k1 $at #保存$at”我对组装还比较陌生,所以任何帮助都非常感谢!

.data
myarray: .word 4, 1, 3, 2, 16, 9, 10, 14, 8, 7
arraysize: .word 10
str1: .asciiz "Unsorted array: "
str2: .asciiz "\nSorted array: "
nline: .asciiz "\n"

.text
.globl main

main:
    li      $v0, 0
    la      $t1, myarray #Coping base address of array into $t1
loop1: #Printing unsorted array
    bge $t0, 10, sortFlag
    lw      $t2, 0($t1) # loading word from addrs, then goes to the next addrs
    addi    $t1, $t1, 4

    li      $v0, 1 # Syscall to print value 
    move    $a0, $t2
    syscall
    li      $a0, 32 # Syscall number for printing space
    li      $v0, 11  
    syscall

    addi    $t0, $t0, 1 # Incrementing counter
    j      loop1
sortFlag:
    add $t6, $0, $0 # t6 holds flag to determine whether the list is sorted
    la  $a1, myarray # Sets $a1 to base address of array
sort:
    lw  $t2, 0($a1) #Sets $t0 to current element in array
    lw  $t3, 4($a1) #Sets $t1 to next element in array
    slt $t5, $t2, $t3 # Sets $t5 if $t0 < $t1
    beq $t5, $0, swap #Swaps if $t5 = 1
    add $t6, $0, 1 #Check list again if swapped
    sw  $t2, 4($a1) #Storing greater numbers in higher position in the array
    sw  $t3, 0($a1) #Storing lesser numbers in lower position in the array
swap:
    addi $a1, $a1, 4 #Moves to next location in array
    bne  $a1, $t6, sort #If $a0 doesn't equal the end of the array, jump to sort
    bne  $t6, $0, sortFlag #If $t6 = 1, jump to sortFlag
loop2: #Repeated from above to re-print the now sorted array
    bge     $t7, 10, exit

    lw      $t4, 0($t1)
    addi    $t1, $t1, 4

    # syscall to print value
    li      $v0, 1      
    move    $a2 $t4
    syscall

    li      $a2, 32
    li      $v0, 11  
    syscall

    addi    $t7, $t7, 1
    j      loop2
 exit:
    li      $v0, 10
    syscall
gajydyqb

gajydyqb1#

它告诉您在0x 00400068执行的指令正试图使用非法的内存位置。(只需忽略QtSpim突出显示的内容。)
因此,请使用模拟器来确定哪个指令位于0x 00400068。
一旦知道哪个指令是坏的,就可以确定坏的基址寄存器。
一旦知道哪个基址寄存器是坏的,就可以通过使用调试器观察执行情况来找出它是如何变成那样的。
您用于指向单词的指针的值需要开始对齐,并以4的倍数递增。然而,您正在做这些事情,因此这似乎不是一个问题。
因此,可能是循环没有正确终止,算法继续运行,并最终运行到内存末尾。这个猜测也得到了违规地址0x 10040000的支持。该地址靠近或位于全局数据内存的末尾,通常从01 x 0010000开始。因此,对于10的小数组,你的记忆力不应该达到那么高。
开发和调试提示:

  • 当测试一个算法时,用尽可能小的输入来尝试。例如,一个0元素的数组。对于word数据,通常只需将某个计数设置为0就可以了,但是对于字符串,因为它们是以空值结束的,你可能需要先用一个较小的字符串来测试。这将使调试循环和递归变得容易得多。一旦你确定它对0元素有效,然后移动到1个元素,依此类推。

零(有时是1或2)测试边缘情况,所以让它工作应该是一个优先事项。

  • 一次编写一小部分代码,并在开发程序时调试它们。不要等到将整个程序放在一起后才尝试运行它。编写代码时,始终单步执行任何新编写的代码,以确认它是否正常工作。
  • 单步执行并观察每个指令,在每个指令之后,验证它是否按照您的预期运行,没有出现任何意外情况。
  • 了解您的数据及其地址。在调试器中,在单步执行第一行代码之前,您可以检查数据节并查看全局标签和其中的内容。
  • 如果你没有遵循这样的实践,不要期望你的代码在你第一次运行时就能工作。如果任何一条指令是错误的,程序就不会工作,打字错误很容易犯,尤其是在汇编中。
  • 用高级语言开发算法,测试你的算法以确保它工作。然后才翻译成汇编。

这种方法将算法研究与开发从汇编研究、开发和编程中分离出来。(您可以研究的主题范围更大,因为算法不受汇编的约束,而且到汇编的转换也不受算法的约束。)这种方法还确保您在汇编中只处理错别字之类的问题-而不是算法问题,这在程序集中更难调试。

  • 把你的最终算法翻译成汇编语言。不要在这个过程中进行优化。如果你想调整算法,先在C中做,然后知道它能工作,把它带到汇编语言。

另外,寄存器中的变量依赖于模拟器初始化为0,这通常是不好的做法。这种依赖基本上只在非常小的程序中起作用。

  • 调试你自己的代码应该是你的第一步,而不是在没有调试的情况下运行,然后在互联网上向陌生人寻求帮助。(对于一个10元素数组)建议您没有单步调试。如果您进行了单步调试,你应该已经注意到问题了(也就是说,它永远不会停止)。如果你没有调试技能,现在是时候学习它们了。抽象地说,调试程序集与调试其他语言没有什么不同--您只需观察代码一次运行一行,并确保每一行都做正确的事情!
zzoitvuj

zzoitvuj2#

以下是我从该错误消息中收集到的信息(我可能是错的,因为我从未使用过QTspim)

"[80000180] 0001d821 addu $27, $0, $1 ; 90: move $k1 $at # Save $at"

根据使用的寄存器($k1是Linux内核使用的寄存器,$at是一个临时寄存器,用于实现伪指令),以及源代码中任何地方都没有这条指令,我认为您的某个系统调用出现了问题。现在我想起来了,您在这里忘记了一个逗号:move $a2 $t4。请尝试修复该问题,然后看看会发生什么情况。

相关问题