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

NASM中使用scanf读取字符串触发段错误的问题排查

问题分析与解决方案

核心错误点

  • 野指针访问触发段错误:msg1是.bss段用resb 33定义的33字节缓冲区,你却将malloc返回的8字节指针写入[msg1],覆盖了缓冲区前8个字节。后续调用scanf时,你把msg1的地址传给rsi,scanf会将输入字符串写入该地址,直接冲掉之前存储的malloc指针。最后调用printStr时,mov rsi, [msg1]会把输入字符串的前8个字节当作指针,这是无效地址,必然触发段错误。
  • 冗余的动态内存操作:提示字符串是固定内容,完全不需要malloc和strcpy动态分配,直接使用.data段的静态字符串即可,既简化代码又避免内存管理错误。
  • scanf传参逻辑混淆:scanf("%s", buf)的第二个参数是缓冲区的地址,你传递msg1地址的操作是对的,但后续错误地试图读取[msg1]作为指针,导致逻辑混乱。

修正后的代码

SECTION .data
    prompt          db  'hello, insert your name. ', 0
    string_format   db  '%s', 10, 0

SECTION .bss
    input_buf       resb 33  ; 33字节缓冲区,可存储32字符+空终止符

SECTION .text
    extern printf, scanf
    global main

printStr:
    mov rdi, string_format
    xor rax, rax
    call printf
    ret

exit_program:
    mov rdi, 0
    mov rax, 60
    syscall

main:
    ; 打印提示信息
    mov rsi, prompt
    mov rdi, string_format
    xor rax, rax
    call printf

    ; 读取用户输入
    mov rsi, input_buf
    mov rdi, string_format
    xor rax, rax
    call scanf

    ; 回显输入内容
    mov rsi, input_buf
    call printStr

    call exit_program

修正说明

  1. 简化提示字符串定义:将固定提示语移到.data段,避免手动逐个字节初始化,提升代码可读性和维护性。
  2. 移除冗余内存操作:删除不必要的malloc、strcpy和自定义strlen,减少出错点。
  3. 明确scanf传参逻辑:直接传递input_buf的地址作为输入缓冲区,确保scanf写入合法内存区域。
  4. 规范回显操作:直接使用input_buf的地址调用printStr,避免野指针访问。

额外注意事项

  • scanf("%s")会自动在输入末尾添加空终止符,但要确保缓冲区大小足够,防止溢出;如果需要读取含空格的字符串,建议使用fgets替代。
  • 严格遵循x86_64 System V调用约定:函数参数通过rdi、rsi等寄存器传递,简单场景下无需额外保存寄存器,但复杂逻辑中需注意寄存器的保存与恢复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:14:54