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

Linux下NASM汇编程序输出换行异常问题求助

NASM汇编程序输出换行异常排查与修复

问题描述

在Linux环境下使用NASM编写的基础汇编程序,功能是询问用户姓名并输出Hello (姓名) it is very nice to meet you,但实际运行时,it is very nice to meet you会显示在全新一行,而非紧跟在姓名之后。程序代码如下:

global _start

section .text

_start:
        MOV rax, 0x01   ;Writes "What is your name?"
        MOV rdi, 0x01
        MOV rsi, name
        MOV rdx, nameL
        SYSCALL

        MOV rax, 0x00   ;Reads input
        MOV rdi, 0x00
        MOV rsi, name_V
        MOV rdx, 16
        SYSCALL

        MOV rax, 0x01   ;Writes "Hello "
        MOV rdi, 0x01
        MOV rsi, hello
        MOV rdx, helloL
        SYSCALL

        MOV rax, 0x01   ;Writes name value after "Hello "
        MOV rdi, 0x01
        MOV rsi, name_V
        MOV rdx, 16
        SYSCALL

        MOV rax, 0x01   ;Writes greeting after name value
        MOV rdi, 0x01
        MOV rsi, greeting
        MOV rdx, greetingL
        SYSCALL

        MOV rax, 0x3C   ;Exits program
        MOV rdi, 0x00
        SYSCALL

section .data
name: DB "What is your name? "  ;0xA = LINE FEED
        nameL: EQU $ - name     ;get length
        hello: DB "Hello ",
        helloL: EQU $ - hello   ;get length
        greeting: DB " it is very nice to meet you"
        greetingL: EQU $ - greeting     ;get length

section .bss
        name_V: resb 16 ;reserves 16 bytes for user input

问题原因

核心问题出在用户输入处理上:当用户输入姓名后按下回车键,系统会将姓名内容+换行符(ASCII码0xA)一起写入name_V缓冲区。后续输出name_V时,程序会把这个换行符也输出,导致光标跳到下一行,因此后续问候语会显示在新行。此外,输出姓名时使用固定长度16,会把缓冲区里未使用的空字节也输出,可能带来额外异常。

修复方案

读取用户输入后,需要完成两个关键处理:

  1. 定位缓冲区中的换行符,将其替换为字符串结束符0x00,避免输出换行。
  2. 记录用户实际输入的有效长度(不含换行符),输出姓名时使用该长度,而非固定的16。

修改后的代码如下:

global _start

section .text

_start:
        ; 输出询问语句
        MOV rax, 0x01
        MOV rdi, 0x01
        MOV rsi, name
        MOV rdx, nameL
        SYSCALL

        ; 读取用户输入,rax返回实际读取的字节数(含换行符)
        MOV rax, 0x00
        MOV rdi, 0x00
        MOV rsi, name_V
        MOV rdx, 16
        SYSCALL

        ; 保存输入长度到rbx,替换换行符为0
        MOV rbx, rax
        DEC rbx                  ; 有效长度为rax-1(减去换行符)
        MOV byte [name_V + rbx], 0x00

        ; 输出"Hello "
        MOV rax, 0x01
        MOV rdi, 0x01
        MOV rsi, hello
        MOV rdx, helloL
        SYSCALL

        ; 输出用户姓名,使用有效长度rbx
        MOV rax, 0x01
        MOV rdi, 0x01
        MOV rsi, name_V
        MOV rdx, rbx
        SYSCALL

        ; 输出问候语
        MOV rax, 0x01
        MOV rdi, 0x01
        MOV rsi, greeting
        MOV rdx, greetingL
        SYSCALL

        ; 退出程序
        MOV rax, 0x3C
        MOV rdi, 0x00
        SYSCALL

section .data
name: DB "What is your name? "
nameL: EQU $ - name
hello: DB "Hello "
helloL: EQU $ - hello
greeting: DB " it is very nice to meet you"
greetingL: EQU $ - greeting

section .bss
name_V: resb 16 ; 预留16字节输入缓冲区

关键修改点

  • 读取输入后,将系统调用返回的实际读取字节数(存在rax)保存到rbx,减去1得到不含换行符的有效长度。
  • 使用MOV byte [name_V + rbx], 0x00将缓冲区中的换行符替换为字符串结束符,避免输出换行。
  • 输出姓名时,rdx寄存器传入有效长度rbx,而非固定的16,避免输出空字节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 12:35:20