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

如何在RISC-V汇编中实现C的puts函数?现有putchar循环调用异常

问题分析与修复

你的代码核心问题出在putchar函数的实现上,导致调用puts时输出未知字符。

1. putchar函数的逻辑错误

你提到测试putchar时能正确输出a0中的字符,但实际上那是因为测试时先调用getchar把字符读到栈上,putchar刚好读取栈上的正确数据。但当puts调用putchar时,a0是从字符串中加载的字符,而putchar却依然去读取栈上的垃圾数据,同时错误地把a2设为字符的ASCII值(而非输出字节数),这就导致了输出空白方块。

错误代码:

putchar:
    # Write the just read character to the terminal 
    addi a2, a0, 0
    li a7, __NR_WRITE
    li a0, STDOUT
    mv a1, sp
    ecall
    ret

修复后的putchar:

putchar:
    # 临时将a0中的字符存入栈中
    addi sp, sp, -4
    sb a0, 0(sp)
    
    # 调用WRITE系统调用:a0=STDOUT, a1=缓冲区地址, a2=字节数, a7=系统调用号
    li a7, __NR_WRITE
    li a0, STDOUT
    mv a1, sp
    li a2, 1  # 输出1个字符
    
    ecall
    
    # 恢复栈指针
    addi sp, sp, 4
    ret

2. puts循环的可选优化

当前puts用地址比较beq a1,a3,puts_loop_end来判断字符串结束,这在你用标签标记字符串末尾的场景下是可行的。如果要让puts支持C风格的以\0结尾的字符串,可以把循环条件修改为检查字符是否为0:

puts:
    puts_loop:
        lb a0, 0(a1)
        beqz a0, puts_loop_end  # 字符为0时结束循环
        jal ra, putchar
        addi a1, a1, 1
        j puts_loop
    puts_loop_end:
        ret

同时需要把.data段的字符串改为.asciz(自动添加终止符):

.data
prompt: .asciz "Enter a message: "

修复后的完整代码

.globl main
.equ STDOUT, 1
.equ STDIN, 0
.equ __NR_READ, 63
.equ __NR_WRITE, 64

.text
main:
    #prolog
    addi sp, sp, -104
    sw ra, 100(sp)
    
    # Load prompt and call puts
    la a1, prompt
    la a3, prompt_end
    jal ra,puts
    
    #epilogue
    lw ra, 100(sp)
    addi sp, sp, 104
    ret

getchar:
    # Read up to 1 character from the terminal (stdin)
    li a7, __NR_READ
    li a0, STDIN
    mv a1, sp
    addi a2, zero, 1
    ecall
    ret

putchar:
    # 临时将a0中的字符存入栈中
    addi sp, sp, -4
    sb a0, 0(sp)
    
    # 调用WRITE系统调用
    li a7, __NR_WRITE
    li a0, STDOUT
    mv a1, sp
    li a2, 1
    
    ecall
    
    # 恢复栈指针
    addi sp, sp, 4
    ret

# puts function
puts:
    puts_loop:
        # load current char into a0
        lb a0,0(a1)
        # check for end of string
        beq a1,a3,puts_loop_end
        # print using putchar
        jal ra,putchar
        # add 1 to a1 to move to next char
        addi a1,a1,1
        j puts_loop
    puts_loop_end:
        ret

.data
prompt: .ascii "Enter a message: "
prompt_end: 

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 08:32:44