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

MIPS汇编数组质数检测异常求助:_prime函数lw指令问题排查

修复MIPS汇编程序中的质数检测函数异常

问题根源分析

你指出的lw $s2,($s0)指令异常,本质是**_prime函数的参数处理逻辑完全错误**:

  • 调用_prime时传入的是数组当前元素的地址(存在$a0),但_prime内部错误地将s0当成数值直接运算,没有先从地址中取出实际元素值。
  • 初始化阶段的寄存器赋值逻辑混乱,导致后续除法、判断全部偏离预期。
  • 额外存在_printprime中打印逻辑的小错误:自增s0后再取元素,会打印下一个数组元素而非当前检测的质数。

修复后的完整代码

.data
arr: .space 100  
input1: .asciiz "Nhap so phan tu: " #input the number elements of the array  
input2: .asciiz "Nhap mang: \n" #input the array  
output1: .asciiz "Mang vua nhap: "  #print the array
output2: .asciiz "\nCac so nguyen to la: "  #print the prime in the array
output3: .asciiz "\nGia tri lon nhat trong mang: "  #print the max element in the array
output4: .asciiz "\nGia tri trung binh cua mang la: "   #print the average value in the array 
output5: .asciiz "a["
output6: .asciiz "]: "
.text
    #print input1
    li $v0,4
    la $a0,input1
    syscall
    #input n
    li $v0,5
    syscall
    #store n into $s1
    move $s1,$v0
    
    #passing parameter into _inputarr
    move $a1,$s1
    la $a0,arr
    jal _inputarr
    #store return value into $s0
    move $s0,$v0
    
    #passing parameter into _outputarr
    move $a1,$s1
    move $a0,$s0

    jal _outputarr
    
    #passing parameter into _printprime
    move $a1,$s1
    move $a0,$s0
    jal _printprime
    
    j exit
_inputarr: 
    #initialize stack
    addi $sp,$sp,-32
    
    #back up register
    sw $s1,($sp)
    sw $s0,4($sp)
    sw $t0,8($sp)
#func's body    
    #initialize variable
    move $s0,$a0
    move $s1,$a1
    li $t0,0 #i=0
    move $s2,$a0
    
    #print input2
    li $v0,4
    la $a0,input2
    syscall
_inputarr.loop:
    beq $t0,$s1,_inputarr.end
    #print 'a['
    li $v0,4
    la $a0,output5
    syscall
    #print i
    li $v0,1
    move $a0,$t0
    syscall
    #print '] '
    li $v0,4
    la $a0,output6
    syscall
    #input a[i] 
    li $v0,5
    syscall
    sw $v0,($s0)
    addi $t0,$t0,1
    addi $s0,$s0,4
    j _inputarr.loop
_inputarr.end:
    move $v0,$s2
    
    #restore register
    lw $s1,($sp)
    lw $s0,4($sp)
    lw $t0,8($sp)
    #restore stack
    addi $sp,$sp,32
    #return 
    jr $ra


_outputarr:
    #initialize stack
    addi $sp,$sp,-32
    
    #back up register
    sw $s1,($sp)
    sw $s0,4($sp)
    sw $t0,8($sp)
#func's body    
    #initialize variable
    li $t0,0 #i=0
    move $s0,$a0
    move $s1,$a1
    
    #print output1
    li $v0,4
    la $a0,output1
    syscall
_outputarr.loop:
    beq $t0,$s1,_outputarr.end
    lw $a0,($s0)
    li $v0,1
    syscall
    #print space
    li $v0,11
    li $a0,' '
    syscall
    addi $t0,$t0,1
    addi $s0,$s0,4
    j _outputarr.loop
_outputarr.end:
    #restore register
    lw $s1,($sp)
    lw $s0,4($sp)
    lw $t0,8($sp)
    #restore stack
    addi $sp,$sp,32
    #return 
    jr $ra

_printprime:
    #initialize stack
    addi $sp,$sp,-32
    
    #back up register
    sw $s0,($sp)
    sw $s1,4($sp)
    sw $t0,8($sp)
    sw $t8,12($sp)
    sw $a0,16($sp)
    sw $t1,20($sp)
#func's body
    #initialize variable
    move $s0,$a0
    move $s1,$a1
    li $t0,0 #i=0
    #print output2
    li $v0,4
    la $a0,output2
    syscall
_printprime.loop:
    beq $t0,$s1,_printprime.end
    # 先保存当前元素地址,避免自增后丢失
    move $a0,$s0
    jal _prime
    #store return value
    move $t8,$v0

    # 先判断是否打印,再自增指针
    beq $t8,0,_printprime.next
    # 打印当前元素
    lw $a0,($s0)
    li $v0,1
    syscall
    li $v0,11
    li $a0,' '
    syscall
_printprime.next:
    addi $t0,$t0,1
    addi $s0,$s0,4
    j _printprime.loop
_printprime.end:
    #restore register
    lw $s0,($sp)
    lw $s1,4($sp)
    lw $t0,8($sp)
    lw $t8,12($sp)
    lw $a0,16($sp)
    addi $sp,$sp,32
    #return
    jr $ra
    
    
_prime: 
    #initialize stack
    addi $sp,$sp,-32
    #back up register
    sw $s0,0($sp)
    sw $s1,4($sp)
    sw $t0,8($sp)
    sw $t8,12($sp)
    sw $s2,16($sp)
    sw $t9,20($sp)
#func's body    
    # 正确处理参数:$a0是元素的地址,先取出数值到$s2
    move $s0,$a0          # 保存传入的元素地址
    lw $s2,($s0)          # 取出当前要检测的数值
    
    # 边界条件判断:小于2的数不是质数
    slti $t8,$s2,2
    beq $t8,1,_prime.false
    # 2是质数,直接返回真
    beq $s2,2,_prime.true
    
    li $t0,2              # 初始化除数i=2
    div $s2,$t0           
    mflo $s1              # $s1 = n/2,循环上限
_prime.loop:
    # 如果i超过n/2,说明是质数
    sgt $t8,$t0,$s1
    beq $t8,1,_prime.true
    # 取余判断是否能整除
    div $s2,$t0
    mfhi $t9
    beq $t9,0,_prime.false # 能整除则不是质数
    addi $t0,$t0,1
    j _prime.loop
_prime.false:
    li $v0,0
    j _prime.end
_prime.true:
    li $v0,1
#end of func
_prime.end:
    #restore register
    lw $s0,0($sp)
    lw $s1,4($sp)
    lw $t0,8($sp)
    lw $t8,12($sp)
    lw $s2,16($sp)
    lw $t9,20($sp)
    #restore stack
    addi $sp,$sp,32
    #return
    jr $ra
exit:
    li $v0,10
    syscall # 补充缺失的syscall指令

关键修改点说明

  1. _prime函数参数修正

    • 首先将传入的元素地址($a0)保存到$s0,再通过lw $s2,($s0)取出实际数值,这是你原代码最核心的错误。
    • 补充了边界条件:小于2的数直接判定为非质数,2直接判定为质数,避免无效循环。
  2. _printprime函数打印逻辑修正

    • 将指针自增操作移到打印判断之后,避免原代码中自增后取到下一个元素的错误。
    • 新增_printprime.next分支统一处理自增逻辑,代码更清晰。
  3. 其他细节修复

    • 在exit标签处补充了syscall指令,确保程序能正常退出。
    • 调整了_prime中循环上限的计算逻辑,移除了多余的addi $s1,$s1,1,避免循环次数错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:07:02