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,会把缓冲区里未使用的空字节也输出,可能带来额外异常。
修复方案
读取用户输入后,需要完成两个关键处理:
- 定位缓冲区中的换行符,将其替换为字符串结束符
0x00,避免输出换行。 - 记录用户实际输入的有效长度(不含换行符),输出姓名时使用该长度,而非固定的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
相关产品推荐
相关产品推荐

