我尝试打印一个字符由逗号分隔的数组,例如:{1,2,3...}为了实现这一点,我在代码的.data部分声明了一个变量separator: .asciiz ", "
。然而,我在.data部分中有一些其他变量,我相信它们在自己的地址中创建了一个意想不到的结果。
.data
numero: .word 0
prompt: .ascii "Digite el valor de n: "
incorrecto: .ascii "Digite el valor de n: "
lista_numerador: .space 40
separator: .asciiz ", "
espacio1: .space 40
lista_denominador: .space 40
.text
main:
jal getNumber
lw $s0, numero
addi $a0, $v0, 0
jal numerador
jal denominador
jal print_list
addi $v0, $0, 10
syscall
print_list:
la $s1, lista_numerador
addi $t0, $0, 0
addi $s0, $a0, 0 #s0 = 4
mul $s1, $a0, $a0
print_loop:
slt $t3, $t0, $s1 # t3 = 1 if i < 4*4
beq $t3, $0, end_print
sll $t1, $t0, 2 # i*4
add $t2, $a1, $t1 # A + i*4
lw $a0, ($t2)
addi $v0, $0, 1
syscall
la $a0, separator
addi $v0, $0, 4
syscall
addi $t0, $t0, 1
j print_loop
end_print:
jr $ra
我已经看到,根据我是否将“分隔符”行放在数组行的前面,后面或中间,一切都会发生变化(我有一个错误,其中一个数组地址以7结尾,而不是4的倍数)。使用当前代码,我在MARS中的输出是这样的:
显然,预期的结果是{1,1,1,1,2,2,2,...},但我得到了那些奇怪的盒子。
我认为问题的原因是$a0在la $a0, separator
行中得到的地址,MARS说它的值是0x 10010058,但我不知道正确的期望值是什么。
任何后见之明都是非常赞赏的。谢谢!
如果我没有为lista_denominador创建内存空间,它将正确打印。
1条答案
按热度按时间iibxawm41#
当你进入MARS模拟器时,它在执行第一条机器代码指令之前就停止了(你必须告诉它运行或单步执行),但是你可以在内存和寄存器中查看加载的二进制程序的初始状态。
这使您有机会检查二进制文件,这里是内存中的数据,它是由程序集中的
.data
节声明带来的。类似于“文本段”窗口,它包含汇编的机器代码指令,我们用于单步调试,有一个“数据段”窗口,您可以使用它来查看数据。此外,还有一个“标签”窗口,当程序被加载到内存中时,显示标签名称和它们的最终地址。
因此,您可以参考“Labels”窗口来查找声明为
separator: .asciiz ", "
的字符串的地址-只需查找与separator
关联的地址。然后调整“数据段”窗口以显示该内存位置周围的地址。不像“文本段”,你可以用鼠标上下滚动,在“数据段”,而不是有两个不方便的箭头来移动显示“数据段”窗口的内存位置的视图。
您只能移动窗口一个固定的数量,所以您通常只能接近看到您想要的内容,并且您必须计数列来找到您的数据;也不方便但也是一件合乎逻辑的事情,所以你可以找到感兴趣的确切地址。此外,默认情况下,存储器显示为非ASCII字,但数据段窗口中有一个“ASCII”的切换。
一个逗号后面跟一个空格可能有点难以找到,所以你可以暂时把这个声明变成一个更大、更容易识别的字符串,这样你就可以用更少的精力找到正确的位置。
较大的字符串将同样被程序的数组索引超出界限而丢弃。一种方法是查看字符串的第一个字符何时被删除。它将发生在单个指令上,并且在单个步骤期间是可观察到的。
一个正确的程序不会超出数组的范围(特别是覆盖字符串之前的数组)。在任何情况下,发生这种情况的确切点(一条指令)可以在调试器中观察到,并且您应该查看那里的代码,以查看算法中是否存在错误,因为某种原因意外地通过数组的末尾,或者数组和循环迭代计数不匹配,因为数组对于您正在使用的数据集来说太小,正如其他人所提到的那样。请记住,字是32位宽的,每个字占用4个存储器位置,因此也占用4个存储器地址。