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

实现数独已解单元格计数函数遇溢出及地址错误求助

数独已解单元格计数函数的溢出与地址错误分析

问题根源

你的代码存在几个致命错误,直接导致了算术溢出警告和"Bad address in data/stack"错误:

  • 无视传入参数,硬编码全局board地址:
    函数设计要求通过$a0传入棋盘指针,但你用la $s0, board直接加载全局变量地址,完全跳过了传入参数。如果调用时传入的地址和全局board不匹配,或者全局board的内存区域无法正常访问,必然触发地址错误。

  • 寄存器被子函数覆盖,逻辑彻底混乱:
    你把计数器存在$v0中,但jal is_cell_solved调用后,子函数的返回值会直接覆盖$v0。之后执行的addi $v0, $v0, 1根本不是在递增原计数器,而是基于子函数的返回值做修改,这不仅会导致计数完全错误,还可能因为子函数返回异常值引发算术溢出。

  • 违反MIPS寄存器调用约定:
    $s0属于被调用者保存寄存器,你的函数直接使用它却没有先保存到栈中,会破坏调用者的寄存器状态,进而引发栈或数据地址的混乱。

  • 计数逻辑完全不符合需求:
    不管单元格是否已解都强制加1,完全违背了"统计已解单元格数量"的要求,属于核心功能逻辑错误。

修正方案与代码示例

按照MIPS调用约定和功能需求,修正后的代码如下:

# a0: pointer to board
# v0: number of solved cells

count_solved_cells:
    addi $sp, $sp, -12      # 为保存寄存器分配栈空间($s0, $s1, $ra)
    sw $s0, 0($sp)
    sw $s1, 4($sp)
    sw $ra, 8($sp)

    li $s1, 0               # 用$s1存计数器,避免被子函数覆盖$v0
    move $s0, $a0           # 把传入的棋盘指针保存到$s0
    li $t0, 81              # 循环计数器:共81个单元格

count_cells_loop:
    move $a0, $s0           # 将当前单元格地址传入子函数的参数寄存器$a0
    jal is_cell_solved      # 调用判断函数,$v0返回1(已解)/0(未解)
    add $s1, $s1, $v0       # 仅当单元格已解时,计数器加1

    addi $s0, $s0, 10       # 移动到下一个单元格(每个占10字节)
    addi $t0, $t0, -1       # 循环次数减1
    bnez $t0, count_cells_loop  # 未遍历完则继续循环

    move $v0, $s1           # 将最终计数赋值给返回寄存器$v0

    lw $ra, 8($sp)          # 恢复栈中保存的寄存器
    lw $s1, 4($sp)
    lw $s0, 0($sp)
    addi $sp, $sp, 12       # 恢复栈指针
    jr $ra

额外检查项

  • 确认is_cell_solved函数的返回值符合预期:必须返回1表示已解,0表示未解,且绝对不能修改传入的单元格数据(满足"不修改棋盘状态"的要求)。
  • 如果仍有溢出警告,检查is_cell_solved是否返回了非0/1的异常值(比如错误返回了单元格数值而非状态)。
  • 验证传入的棋盘指针指向的内存块大小:确保至少有810字节的可读取内存,避免越界访问引发地址错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:05:32