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

MIPS汇编电话簿项目:不同偏移读写数据异常排查求助

MIPS电话簿存储问题分析与排查建议

问题描述

大学MIPS汇编课程项目中,尝试通过内存不同偏移(0、20、40)存储电话簿条目,但加载打印特定偏移的字时,始终获取到最后一个偏移存储的值。

问题代码

Get_Entry:
addi $sp,$sp,-4
sw $ra, 0($sp)  
la $a0,Telephone_base_address

jal Get_Entry_Number
move $a0,$v1
jal Get_Entry_Last_Name
move $a0,$v1
jal Get_Entry_First_Name
move $a0,$v1
jal Get_Entry_Phone_Number

li $v0,4

lw $a0,0($v1)
syscall

lw $ra, 0($sp)          ##restore $ra
addi $sp, $sp, 4

jr $ra
    
Get_Entry_Number:
    addi $sp,$sp,-4
    sw $ra, 0($sp)  
    
    move $t0,$a0 
    
    li $v0, 4
    la $a0, get_entry_number
    syscall
    
    li $v0,12
    syscall
    
    li $t1, 60
    
    mul $t2,$t1,$v0
#addition of Telephone base address with the product 
    add $t3,$t0,$t2
    
    move $v1,$t3

    lw $ra, 0($sp)          ##restore $ra
    addi $sp, $sp, 4
    
    jr $ra

Get_Entry_Last_Name:
    addi $sp,$sp,-4
    sw $ra, 0($sp)  
    
    move $t0,$a0
    
    li $v0, 4
    la $a0, get_entry_last_name
    syscall
    
    li $v0, 8          # syscall code 8 for read_string
        la $a0,buffer    # address of the buffer
        li $a1, 20        
        syscall
        
        sw $a0,0($t0)
    
    #sll $t0,$t0,20
    
    move $v1,$t0
    
    lw $ra, 0($sp)          ##restore $ra
    addi $sp, $sp, 4
    
    jr $ra
    
Get_Entry_First_Name:
    addi $sp,$sp,-4
    sw $ra, 0($sp)            
    
    move $t0,$a0
    
    li $v0, 4
    la $a0, get_entry_first_name
    syscall
    
    li $v0, 8          # syscall code 8 for read_string
        la $a0,buffer     # address of the buffer
        li $a1, 20        
        syscall
    
    sw $a0,20($t0)
    #sll $a0,$a0,20
    
    move $v1,$t0


    lw $ra, 0($sp)          ##restore $ra
    addi $sp, $sp, 4

    jr $ra
    
Get_Entry_Phone_Number:
    addi $sp,$sp,-4
    sw $ra, 0($sp)        
    
    move $t0,$a0
    
    li $v0, 4
    la $a0, get_entry_phone_number
    syscall
    
    li $v0, 8          # syscall code 8 for read_string
        la $a0, buffer      # address of the buffer
        li $a1, 20
        syscall
    
    li $v0, 8          # syscall code 8 for read_string
        move $a0,$t0     # address of the buffer
        li $a1, 20        
        syscall
    
    move $v1,$t0
    
    lw $ra, 0($sp)          ##restore $ra
    addi $sp, $sp, 4
    
    jr $ra

核心问题原因

  • 输入数字未转ASCII码:Get_Entry_Number中用syscall 12读取的是字符的ASCII值(比如输入'0'得到48),直接乘以60计算偏移会导致地址完全错误,后续所有条目都存在了错误的内存区域。
  • 存储的是缓冲区地址而非字符串内容:Get_Entry_Last_Name和Get_Entry_First_Name中,调用syscall 8把字符串读入buffer后,用sw $a0, offset($t0)存储的是buffer的地址,不是字符串本身。所有条目都指向同一个buffer,每次新输入都会覆盖buffer内容,打印时自然只会显示最后一次输入的内容。
  • 电话号码读取逻辑冗余错误:Get_Entry_Phone_Number中连续两次调用syscall 8,第二次直接把输入写入目标地址,不仅覆盖了之前的操作,还破坏了整个条目的存储结构。
  • 打印时的地址引用错误:Get_Entry中用lw $a0,0($v1)加载的是之前存储的buffer地址,而非目标偏移处的字符串内容,进一步导致打印结果始终指向被覆盖的buffer。

排查与修复建议

  • 修正数字输入处理:在Get_Entry_Number中,读取字符后将ASCII码转为数字,比如添加sub $v0, $v0, 48,确保输入'0'得到0、'1'得到1,再计算偏移量。
  • 复制字符串内容而非存储地址:替换sw $a0, offset($t0)为字符串复制逻辑,比如用循环将buffer中的每个字节逐个复制到目标偏移地址(注意包含终止符'\0')。
  • 清理电话号码读取逻辑:删除Get_Entry_Phone_Number中第一次冗余的syscall 8,直接将输入写入目标偏移(比如40($t0)),或者先读入buffer再复制到目标地址,保持和姓名存储逻辑一致。
  • 验证内存地址正确性:使用调试工具(比如MARS的内存查看器)检查每个条目存储的地址和内容,确认偏移计算正确,字符串确实被写入了预期的内存位置。
  • 调整打印逻辑:如果直接在目标地址存储字符串,打印时直接将目标偏移地址加载到$a0即可,无需lw操作(比如la $a0, 0($v1)或者直接用move $a0, $v1)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 17:57:01