MIPS组件排序
我的任务是使用MIPS组装和QTSPIM对硬编码整数数组进行排序和打印。我一直在尝试遵循此处发布的其他类似问题,但我正在努力理解我现在出错的地方。我正在得到“ pc = 0x00400068的例外 数据/堆栈中的不良地址读取:0x10040000” QTSPIM亮点“ [80000180] 0001D821 ADDU $ 27,$ 0,$ 1; 90:Move $ k1 $ at#save $ at at at 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
I've been tasked with sorting and printing a hardcoded integer array using MIPS assembly and QTSpim. I've been trying to follow the other similar questions posted here but I am struggling to understand where I am now going wrong. I'm getting "Exception occurred at PC=0x00400068
Bad address in data/stack read: 0x10040000"
QTSpim highlights "[80000180] 0001d821 addu $27, $0, $1 ; 90: move $k1 $at # Save $at"
I'm fairly new at assembly, so any help is much appreciated!
.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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
它告诉您,执行0x00400068的指令正在尝试使用非法内存位置。 (只需忽略QTSPIM亮点即可。)
因此,使用模拟器来识别哪个指令在0x00400068。
一旦知道哪种说明不好,就可以识别不良的基本寄存器。
一旦知道哪个基本寄存器不好,您就可以通过使用调试器观察执行方式来找出它如何得到的。
您用于指示单词的值需要启动对齐,并通过4的倍数增加。但是,您正在做这些事情,因此在这里似乎并不是一个问题。
因此,可能的是,循环无法正确终止,并且该算法继续延续并最终从内存的结尾开始运行。&nbsp;此预感也得到了有问题地址0x10040000的证据。&nbsp;该地址在全局数据存储器的接近或结束时,通常始于01x0010000。&nbsp;因此,有了10个小阵列,您就不应该达到这么高的内存。
发展&amp;调试提示:
测试算法时,请尝试使用最小的输入。&nbsp;例如,一个0个元素的数组。&nbsp;使用单词数据,通常可以通过仅将一些计数设置为0来完成,但是使用字符串,由于它们是nul终止的,因此您可能需要先用较小的字符串测试。&nbsp; nbsp;这将使调试循环和递归变得更加容易。一旦您确定其适用于0个元素,然后继续进行1个元素,依此类推。
零(或有时1或2)测试边缘案例,因此使工作应该是优先级。
一次编写代码的小部分,并在开发程序时调试它们。&nbsp;不要等到整个程序一起尝试运行它。&nbsp;编写代码总是单步,您编写的任何新代码都可以确认它正在工作。
单步并观察每个指令,每个说明之后,验证它可以执行您的期望,而无需您期望。
了解您的数据及其地址。&nbsp;在登上第一行代码之前,在调试器中,您可以检查数据部分,并查看您的全局标签和其中的内容。
如果您没有遵循这样的练习,则不要期望您的代码第一次运行。&nbsp;如果任何一个指令是错误的,则该程序将无法正常工作,尤其是在汇编中可以易于制作。
。
以高级语言开发算法,测试您的算法以确保其有效。&nbsp;然后才转化为集会。
这种方法解除了算法研究&amp; amp;来自集会研究,开发和编程的发展。&nbsp; (您可以研究的主题范围更大,因为该算法不受限制地组装,并且对组装的翻译不受算法的约束。)&nbsp;这种方法还确保您只有在汇编中可以处理错别字,而不是算法问题,而算法问题很难在组装中进行调试。
将您的最终算法转换为字面上的组装。&nbsp;不要在此过程中进行优化。&nbsp;如果要调整算法,请首先在C中执行此操作,然后知道它有效,将其用于组装。
另外,您在寄存器中有变量,您依靠模拟器来初始化为0,这通常是不好的练习。&nbsp;这种依赖基本上仅在很小的程序中起作用。
调试您自己的代码应该是您的第一个首选,而不是在不调试的情况下运行,然后在Internet上向陌生人寻求帮助。&nbsp;您没有注意到它正在运行成千上万的迭代(对于10个元素数组)表明您没有单步访问此步骤。&nbsp;如果您完成了单步调试,则应该注意到问题(即它永远不会停止)。&nbsp;如果您没有调试技能,那么现在是时候获取它们了。&nbsp;在抽象的情况下,调试组件与调试其他语言没有什么不同 - 您只需观看代码一次运行一行即可确保每行都做正确的事情!
It is telling you that the instruction executing at 0x00400068 is attempting to use an illegal memory location. (Just ignore the QtSpim highlights.)
So, use the simulator to identify which instruction is at 0x00400068.
Once you know which instruction is bad, you can identify the base register that is bad.
Once you know which base register is bad, you can find out how it got that way, by using the debugger to observe execution.
Values you use for pointers to words need to start aligned and be incremented by multiples of 4. However, you're doing these things, so that doesn't appear to be an issue here.
So, what it could be then is that the loop doesn't terminate properly, and the algorithm continues on and eventually runs off the end of memory. This hunch is also supported by the evidence of the offending address 0x10040000. This address is near or at the end of global data memory, which usually starts at 01x0010000. So, with your small array of 10, you shouldn't be reaching that high in memory.
Developing & Debugging tips:
When testing an algorithm, try it with the smallest possible input. For example, an array of 0 elements. With word data, usually that can be done by merely setting some count to 0, but with strings, as they are nul-terminated, you may need to test first with a smaller string. This will make debugging loops and recursion much easier. Once you're sure its working for 0 elements, then move on to 1 element, and so on.
Zero (or sometimes 1 or 2) tests edge cases, so getting that working should be a priority.
Write small parts of code at a time, and debug them as you develop the program. Don't wait until you have a whole program put together to try running it. When writing code always single step any new code you write to confirm it is working.
Single step and observe each instruction and after each, verify it does what you're expecting and nothing you're not expecting.
Get to know your data and its addresses. In the debugger before you step the first line of code, you can inspect your data section and see your global labels and the content there.
Don't expect your code to work the first time you run it if you haven't followed practices like these. If any one instruction is wrong, the program won't work, and typos are easy to make especially in assembly.
Develop algorithms in high level language, test your algorithm to make sure it works. And only then translate to assembly.
This approach decouples algorithm research & development from assembly research, development and programming. (The range of topics you can research is larger since the algorithm isn't constrained to assembly and the translation to assembly isn't constrained by the algorithm.) This approach also ensures you'll only have typos and such to deal with in assembly — instead of algorithmic problems, which are way harder to debug in assembly.
Translate your final algorithm into assembly quite literally. Don't optimize in the process. If you want to tweak the algorithm, do that in C first then knowing it works, take it to assembly.
Also you have variables in registers that you're relying on the simulator to initialize to 0, which is generally bad practice. This reliance basically only works in very small programs.
Debugging your own code should be your first go-to rather than running without debugging and then asking strangers on the internet for help. That you didn't notice it is running hundreds of thousands of iterations (for a 10 element array) suggests you didn't single step debug this. Had you done single step debugging, you should have noticed problems (i.e. it never stops). If you don't have debugging skills, now is the time to acquire them. In the abstract, debugging assembly is no different from debugging other languages — you just watch your code run one line at a time and make sure each line does the right thing!
我从未使用过QTSPIM,我可能是错误的)
这是我从该错误消息中收集的内容(由于 是用于实现伪指令的临时寄存器),以及此指令不在您的源代码中,我认为您的一个syscall出现了问题。现在我考虑了一下,您在这里忘记了一个逗号:
移动$ a2 $ t4
。尝试修复它,看看会发生什么。Here's what I gather from that error message (I could be wrong since I've never used QTspim)
Based on the registers in use (
$k1
is used by the Linux kernel, and$at
is a temporary register that is used to implement pseudo-instructions), as well as this instruction not being in your source code anywhere, I'm thinking something went wrong with one of your syscalls. Now that I think about it, you forgot a comma here:move $a2 $t4
. Try fixing that and see what happens.