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

QTSPIM中整数转字符串循环的sb指令报错,求技术排查帮助

解决QTSPIM中整数转字符串的非法地址错误

你遇到的Bad address in data/stack read: 0x0000003f错误,根源是地址处理逻辑错误,把ASCII字符值当成了内存地址使用,以下是具体问题和修复方案:

核心问题与修复

1. 非法地址初始化

在update_and_store_red段中,move $t4, $t2是致命错误:此时$t2是从read_red读取的ASCII字符(比如空格的ASCII码32),你把这个字符值当作buffer的地址使用,后续addi $t2, $t2, 31得到32+31=63(0x3f),这显然不是buffer的合法内存地址,导致存储时触发非法访问。

修复代码:

update_and_store_red:
    move $t0, $t8       # Copy the integer to convert     
    la $t4, buffer       # 加载buffer的基地址到$t4
    addi $t2, $t4, 31    # 指向buffer的第32个字节(索引31),用来存字符串终止符
    sb $zero, ($t2)      # 写入字符串终止符
    addi $t2, $t2, -1    # 移动指针到前一个位置,准备存储数字字符
    jal int_to_string
    li $v0, 15          # System call code for writing a byte
    move $a0, $s1       # File descriptor
    move $a1, $t4       # 从buffer基地址开始写入
    li $a2, 32          # 写入32字节(buffer的前32位,可根据实际调整)
    syscall
    # ... 其他代码保持不变

2. max_val取值错误

prep_to_read_pixels中的la $t6, max_val是加载max_val的内存地址,而非它的实际数值,后续ble $t8, $t6是拿整数和地址比较,逻辑完全错误。

修复:

prep_to_read_pixels:
    # ... 其他初始化代码
    lw $t6, max_val     # 加载max_val的实际数值(255),而非地址
    # ... 其他代码

3. int_to_string中的冗余代码

int_to_string开头的addi $t7, $t7, 1完全多余,$t7在此函数中没有作用,还会破坏寄存器原有值,直接删除即可。

修复后的int_to_string:

int_to_string:
    div $t0, $t0, 10                # Divide $t0 by 10 (quotient in $t0, remainder in $t3)
    mflo $t0                        # 更新$t0为商
    mfhi $t3                        # 获取余数到$t3
    addi $t3, $t3, 48               # 转换为ASCII字符
    sb $t3, 0($t2)                  # Store the ASCII character in the buffer
    addi $t2, $t2, -1               # 左移指针,准备存储下一个字符
    bnez $t0, int_to_string         # 商不为0则继续循环
done:
    jr $ra

4. 系统调用参数错误

la $a2, 64是尝试加载地址64,而系统调用15(文件写入)需要的是写入的字节数,应该用li指令加载数值:

li $a2, 32  # 替换原有的la $a2,64,这里用32是因为我们用了buffer的32字节区域

修复后的完整代码

.data
    header_buffer:              .asciiz "123 "
    width:              .word 0         # Integer to store width of file
    height:             .word 0         # Integer to store height of file
    max_val:            .word 0         # Integer to store maximum value of a pixel
    num_pixels:         .word 0         # Integer to store number of pixels in file 
    buffer:             .space 128
    filename:           .asciiz "input.ppm"
    output_filename:    .asciiz "output.ppm"


.text
    .globl main
    
    
main:
    li $t0, 64
    sw $t0, width
    sw $t0, height
    li $t0, 255
    sw $t0, max_val
    li $t0, 12288
    sw $t0, num_pixels
    

# Open the output file for writing
open_output:
    li $v0, 13          # System call code for opening a file (write mode)
    la $a0, output_filename
    li $a1, 1           # File mode (write)
    li $a2, 0
    syscall
    move $s1, $v0       # Save the file descriptor in $s1

    
# Initialise registers 
prep_to_read_pixels:
    li $s2, 0           # Sum of R values
    li $s3, 0           # Sum of G values
    li $s4, 0           # Sum of B values
    
    li $t5, 0           # Pixel counter
    lw $t6, max_val     # 修复:加载max_val的数值而非地址
    li $t8, 0           # Int value of pixel 
    la $t1, header_buffer
    li $t0, 0

read_red:

    lb $t2, 0($t1)                      # Load the read character
    move $t7, $t2                       # Copy read char to $t7
    addi $t1, $t1, 1                    # Move pointer
    addi $t0, $t0, 1                    #track num digits in number
    addi $t9, $t9, 1                    # Increment - change position of the end of header to the current end
    beq $t2, 32, incr_red               # Check if char is whitespace 
    beq $t2, 10, incr_red               # Check if char is new line
    jal loop_to_convert
    j read_red
    
incr_red:
    addi $t5, $t5, 1
    add $s2, $s2, $t8
    addi $t8, $t8, 10
    ble $t8, $t6, update_and_store_red
    jal clamp   
    j update_and_store_red



    
update_and_store_red:
    move $t0, $t8       # Copy the integer to convert     
    la $t4, buffer       # 修复:加载buffer基地址
    addi $t2, $t4, 31    # 修复:指向buffer的第32字节位置
    sb $zero, ($t2)      # 写入字符串终止符
    addi $t2, $t2, -1    # 移动指针到前一位
    jal int_to_string
    li $v0, 15          # System call code for writing a byte
    move $a0, $s1       # File descriptor
    move $a1, $t4       # 从buffer基地址开始写入
    li $a2, 32       # 修复:用li加载数值而非la加载地址
    syscall
    li $t2, 0
    li $t0, 0
    beq $t5, 1, exit
    j read_red
    

exit:
    # Close the file
    li $v0, 16           # Close syscall code
    move $a0, $s1        # File descriptor
    syscall

    # Exit the program
    li $v0, 10           # Exit syscall code
    syscall

loop_to_convert:
    addi $t7, $t7, -48      # Convert ascii char to digit equivalent by subtracting "0" (ascii code 48)
    mul $t8, $t8, 10        # Multiply the running total by 10
    add $t8, $t8, $t7       # Add new digit to running total
    jr $ra                  # Jump back
    
clamp:
    li $t8, 255    # Clamp value to 255
    jr $ra
    
int_to_string:
    div $t0, $t0, 10                # Divide $t0 by 10 (get quotient in $t0, remainder in $t3)
    mflo $t0                        # Quotient
    mfhi $t3                        # Remainder
    addi $t3, $t3, 48               # Convert to ASCII      
    sb $t3, 0($t2)                  # Store the ASCII character in the buffer
    addi $t2, $t2, -1               # Move the pointer to the left in the buffer
    bnez $t0, int_to_string         # Repeat until $t0 becomes zero
done:
    jr $ra

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:54:55