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

MIPS读取5个整数逆序输出程序$sp栈指针使用问题咨询

MIPS程序栈指针$sp使用问题排查与修正

现有代码的核心问题

1. 寄存器初始化缺失

你在main函数中调用输入子程序while前,没有给循环计数器$t0赋初始值0,输入循环的触发逻辑完全不可控。你观察到输入阶段$sp没有变化,根本原因是默认初始值下$t0等于20,输入循环直接跳过,循环内的栈操作代码根本没有执行,$sp自然保持初始值不变。

2. 栈操作逻辑完全错位

MIPS子程序的栈保存/恢复逻辑应该在子程序的入口和出口各执行一次,而不是放在循环体内:

  • 你现在把栈分配代码addi $sp, $sp, -8放在输入循环内部,每输入1个数就占用8字节栈空间,5次输入就会占用40字节栈空间,最后你只在程序退出前恢复了1次8字节空间,栈完全失衡,不符合$sp始终指向最后一个已占用栈单元的要求。
  • 你循环内重复保存$s0和$ra属于冗余操作,没有任何实际意义,反而会不断下移$sp。

3. 栈恢复时机错误

你把栈恢复逻辑写在了打印结束后的exitOutput段,和输入子程序的栈分配逻辑完全不对应,这也是你观察到打印阶段$sp才发生变化的直接原因。

修正方案

  1. main函数调用输入子程序前,给$t0赋值初始值0
  2. 把输入子程序的栈分配、寄存器保存逻辑移到子程序入口,仅执行一次
  3. 输入子程序退出前,先恢复寄存器、回收栈空间,再返回主程序
  4. 删除冗余的栈操作代码,保证栈操作的配对性

修正后完整代码

.data
     arr: .space 20 # 长度为5的整型数组
     inputPrompt: .asciiz "Please enter a whole number: \n"
     spaceChar: .asciiz " "
     
.text
     main:
     # 初始化输入循环计数器
     li $t0, 0
     # 提示用户输入
     li $v0, 4
     la $a0, inputPrompt
     syscall
     
     jal while
     
     # 初始化打印计数器,从数组最后一个元素开始
     addi $t0, $zero, 16
     jal whileOutput

     # 程序正常退出
     li $v0, 10
     syscall

     # 输入子程序
     while:
            # 子程序入口:分配8字节栈空间,保存需要用到的寄存器
            addi $sp, $sp, -8
            sw $s0, 0($sp) 
            sw $ra, 4($sp)
     inputLoop:
            beq $t0, 20, exitWhile
            
            # 读取输入
            li $v0, 5
            syscall
            
            sw $v0, arr($t0)
            move $s0, $v0
            
            addi $t0, $t0, 4
            j inputLoop
     
     exitWhile:
            # 子程序出口:恢复寄存器,回收栈空间
            lw $s0, 0($sp)
            lw $ra, 4($sp)
            addi $sp, $sp, 8
            jr $ra 
        
     # 打印子程序
     whileOutput:
            beq $t0, -4, exitOutput

            lw $t6, arr($t0)
            # 打印整数
            li $v0, 1
            move $a0, $t6
            syscall
            # 打印空格
            li $v0, 4
            la $a0, spaceChar
            syscall
        
            addi $t0, $t0, -4
            j whileOutput
            
     exitOutput:
            jr $ra

修正后$sp的运行逻辑

  • 进入输入子程序时,$sp减8指向新分配的栈空间,符合指向最后一个已占用单元的要求
  • 整个输入循环过程中$sp不会变化,不需要重复分配栈空间
  • 输入子程序退出时,$sp加8恢复到调用前的状态,栈完全平衡
  • 打印阶段没有栈操作,$sp保持不变

内容的提问来源于stack exchange,提问作者S. Jilani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:15:04