assembly MIPS中的意外数据内存地址,无法打印正确的asciiz字符

tjvv9vkg  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(159)

我尝试打印一个字符由逗号分隔的数组,例如:{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创建内存空间,它将正确打印。

iibxawm4

iibxawm41#

当你进入MARS模拟器时,它在执行第一条机器代码指令之前就停止了(你必须告诉它运行或单步执行),但是你可以在内存和寄存器中查看加载的二进制程序的初始状态。
这使您有机会检查二进制文件,这里是内存中的数据,它是由程序集中的.data节声明带来的。类似于“文本段”窗口,它包含汇编的机器代码指令,我们用于单步调试,有一个“数据段”窗口,您可以使用它来查看数据。
此外,还有一个“标签”窗口,当程序被加载到内存中时,显示标签名称和它们的最终地址。
因此,您可以参考“Labels”窗口来查找声明为separator: .asciiz ", "的字符串的地址-只需查找与separator关联的地址。
然后调整“数据段”窗口以显示该内存位置周围的地址。不像“文本段”,你可以用鼠标上下滚动,在“数据段”,而不是有两个不方便的箭头来移动显示“数据段”窗口的内存位置的视图。
您只能移动窗口一个固定的数量,所以您通常只能接近看到您想要的内容,并且您必须计数列来找到您的数据;也不方便但也是一件合乎逻辑的事情,所以你可以找到感兴趣的确切地址。此外,默认情况下,存储器显示为非ASCII字,但数据段窗口中有一个“ASCII”的切换。
一个逗号后面跟一个空格可能有点难以找到,所以你可以暂时把这个声明变成一个更大、更容易识别的字符串,这样你就可以用更少的精力找到正确的位置。
较大的字符串将同样被程序的数组索引超出界限而丢弃。一种方法是查看字符串的第一个字符何时被删除。它将发生在单个指令上,并且在单个步骤期间是可观察到的。
一个正确的程序不会超出数组的范围(特别是覆盖字符串之前的数组)。在任何情况下,发生这种情况的确切点(一条指令)可以在调试器中观察到,并且您应该查看那里的代码,以查看算法中是否存在错误,因为某种原因意外地通过数组的末尾,或者数组和循环迭代计数不匹配,因为数组对于您正在使用的数据集来说太小,正如其他人所提到的那样。请记住,字是32位宽的,每个字占用4个存储器位置,因此也占用4个存储器地址。

相关问题