You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

qtSPIM运行MIPS代码循环后打印字符串输出空字符/空格问题

qtSPIM运行MIPS汇编字符串打印异常排查

问题现象

  • 字符串打印逻辑放在循环代码段之后时,qtSPIM控制台输出异常:要么显示形似空心方块的空字符,要么输出多个空格组成的空串
  • 将字符串打印逻辑移到所有循环之前执行时,可正常输出
  • 尝试在循环结束后重置寄存器,问题未解决

复现代码与输出差异

问题代码

.data

arrayY: .word 1, 2, 3, 4, 5                # 5元素数组
arrayZ: .word -5, -4, -3, -2, -1           # 5元素数组
arrayX: .word 20                            # 仅分配了1个word空间,不足以存5个元素
var1: .asciiz "X: "
var2: .asciiz ", "

.text
.globl main

main:
    addi $a2, $zero, 5      # 初始化n
    addi $s0, $zero, 2      # 初始化s
    addi $s1 $zero, 1       # 语法错误:$s1后漏写逗号

    addi $sp, $sp, -12
    sw $s1, 4($sp)          # 压栈
    sw $s0, 0($sp)
    jal AVA



AVA:
    li $v0, 0
    li $v1, 0
    addi $t1, $a2, -1
    addi $t1, $zero, 20     # 覆盖了上一行计算的数组长度,错误将循环上界设为20
    addi $t0, $zero, 0
    LOOP:
        beq $t0, $t1, exit
        lw $t2, arrayY($t0)
        lw $t3, arrayZ($t0)
        subu $t4, $zero, $t3
        add $t5, $t4, $t2 
        addi $t3, $zero, 2
        mult $t3, $s0
        add $t6, $t3, $s1

        lw $s0, 0($sp)
        lw $s1, 4($sp)
        addi $sp, $sp, 12   # 错误:每次循环都恢复栈指针,栈分配/释放不成对

        add $t7, $t5, $t6
        sw $t7, arrayX($t0)

        addi $t0, $t0, 4
        j LOOP
    exit:
    addi $t0, $zero, 0
    move $a0, $0
    move $v0, $0
    li $v0, 4
    la $a0, var1
    syscall
    LOOP1:
        beq $t0, $t1, exit1
        lw $t2, arrayY($t0)
        move $a0, $t2
        li $v0, 1
        syscall
        addi $t0, $t0, 4
        j LOOP1
    exit1:
    li $v0, 10          # 程序退出
    syscall

预期输出

X: 12345

实际输出

12345

根因分析

代码存在3处核心错误,直接导致内存被意外覆盖,打印字符串时原始内容已经损坏:

  • 栈操作逻辑错误:进入AVA前仅分配了12字节栈空间,但循环体每轮迭代都会执行addi $sp, $sp, 12抬升栈指针。第一轮循环结束后栈指针就回到了分配前的位置,后续循环读栈、写栈会直接访问栈帧外的内存,甚至篡改数据段存储的内容。
  • 数组越界:arrayX仅用.word 20分配了4字节(1个word)的空间,不足以存储5个int元素,而arrayX后紧邻存储的就是var1字符串,循环写arrayX的后续元素时,直接覆盖了var1的内存,原本存的"X: "被改写为空格/空字符,打印时自然无法正常显示。
  • 循环上界设置错误:代码先计算了数组合法偏移上界,随即又用addi $t1, $zero, 20将上界改为20,5个word元素的数组合法偏移为0/4/8/12/16,偏移到20时已经访问到数组外的内存,进一步加剧了内存越界篡改问题。

修复要点

  • 栈操作成对出现:将循环内的lw $s0, 0($sp)、lw $s1, 4($sp)、addi $sp, $sp, 12栈恢复逻辑移到循环外、函数返回前执行,禁止在循环内反复调整栈指针。
  • 给arrayX分配足够空间:将定义改为arrayX: .word 20, 0, 0, 0, 0或arrayX: .space 20,预留5个word共20字节的存储空间,避免数组写越界覆盖后续字符串。
  • 修正循环上界:删除addi $t1, $zero, 20这行覆盖上界的代码,根据数组实际长度计算循环终止的偏移值。
  • 补上指令中遗漏的逗号,修正语法错误。

内容的提问来源于stack exchange,提问作者spencer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 16:31:36