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

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

关键修改说明

  1. 输入缓冲区扩容:用times 256 db 0创建256字节缓冲区,足够存储常规用户输入,且初始全为0,避免残留垃圾数据。
  2. 初始化rcx:strlen开头用xor rcx, rcx清零计数器,原代码未初始化,rcx初始值随机会导致长度计算完全错误。
  3. 手动添加空终止符:read调用后,rax存储实际读取的字节数,直接在rl + rax位置写入0,让strlen能正确识别字符串末尾。
  4. 限制读取长度:rdx设为255,留1字节给空终止符,防止缓冲区溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:45:31