x86_64 NASM中read系统调用未自动添加空终止符的解决方法
解决汇编程序中read无空终止符导致的乱码问题
你的代码存在两个核心问题:一是输入缓冲区rl仅分配1字节,根本存不下用户输入;二是read系统调用不会自动添加空终止符,且strlen未初始化长度计数器,导致长度计算错误。以下是简单直接的修复方案:
核心修复步骤
- 给输入缓冲区分配足够空间,避免溢出
- 利用
read的返回值手动添加空终止符 - 初始化
strlen的长度计数器
修改后的完整代码
global _start section .data str: db "What is your name?", 10, 0 ; 带空终止符的提示字符串 rl: times 256 db 0 ; 256字节输入缓冲区,初始化为0 section .text _start: mov rsi, str call stdout ; 输出提示语句 call stdin ; 读取用户输入 call stdout ; 打印输入内容 jmp ExitSuccess ; 正常退出 strlen: push rsi ; 保存字符串指针 xor rcx, rcx ; 初始化长度计数器为0,必须操作! strlen_next: cmp [rsi], byte 0 ; 检查当前字节是否为空终止符 jz strlen_null ; 是则跳转到结束 inc rcx ; 长度+1 inc rsi ; 指针移到下一个字节 jmp strlen_next ; 循环检查 strlen_null: pop rsi ; 恢复字符串指针 ret ; 返回 stdin: mov rax, 0 ; syscall read的编号是0 mov rdi, 0 ; 文件描述符STDIN mov rsi, rl ; 输入缓冲区地址 mov rdx, 255 ; 最多读255字节,留1字节放空终止符 syscall ; 调用read ; 利用read的返回值(rax是读取的字节数)添加空终止符 cmp rax, 0 ; 检查是否读取成功(rax>0表示读取到内容) jle stdin_end ; 读取失败或无输入则直接返回 mov byte [rl + rax], 0 ; 在输入内容末尾写空终止符 stdin_end: ret stdout: mov rax, 1 ; syscall write的编号是1 mov rdi, 1 ; 文件描述符STDOUT call strlen ; 计算字符串长度,结果存在rcx mov rdx, rcx ; 把长度传给rdx(write需要的参数) syscall ; 调用write ret ExitSuccess: mov rax, 60 ; syscall exit的编号是60 mov rdi, 0 ; 退出码0表示成功 syscall
关键修改说明
- 输入缓冲区扩容:用
times 256 db 0创建256字节缓冲区,足够存储常规用户输入,且初始全为0,避免残留垃圾数据。 - 初始化
rcx:strlen开头用xor rcx, rcx清零计数器,原代码未初始化,rcx初始值随机会导致长度计算完全错误。 - 手动添加空终止符:
read调用后,rax存储实际读取的字节数,直接在rl + rax位置写入0,让strlen能正确识别字符串末尾。 - 限制读取长度:
rdx设为255,留1字节给空终止符,防止缓冲区溢出。
内容的提问来源于stack exchange,提问作者Logan Seeley
相关产品推荐
相关产品推荐

