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

x86 32位汇编程序调用系统调用时未等待第二次输入的问题

问题分析

你的代码存在两个核心问题:

1. Write系统调用的文件描述符错误

sys_call函数中统一执行xor ebx, ebx将文件描述符设为0(标准输入stdin),但write系统调用(eax=4)需要的文件描述符是1(标准输出stdout)。当前代码相当于往标准输入写数据,这不符合预期,虽然终端可能会有输出,但这是错误的实现。

2. 输入缓冲区残留换行符被读取

当你输入一个字符并按下回车时,终端会将输入字符 + 换行符(\n)送入输入缓冲区。第一次read只读取1个字符(你输入的目标字符),剩下的换行符会留在缓冲区中。第二次read会直接读取这个残留的换行符,无需等待用户再次输入,导致程序看似直接退出。

修复方案

步骤1:修正Write系统调用的文件描述符

拆分sys_call的逻辑,在input和write函数中分别设置正确的文件描述符:

  • input(read系统调用):ebx=0(stdin)
  • write(write系统调用):ebx=1(stdout)

步骤2:处理输入后的残留换行符

每次读取目标字符后,额外读取并丢弃输入缓冲区中的换行符,确保下一次read会等待用户输入。

修复后的代码

section .data
    input_buffer1 db 0 ; 存储第一个输入字符
    input_buffer2 db 0
    temp_buffer db 0    ; 临时缓冲区,用于丢弃换行符

section .text
    global _start

_start:
    mov ecx, input_buffer1
    call input
    call write
    call discard_newline ; 丢弃第一次输入后的换行符

    mov ecx, input_buffer2
    call input
    call write
    call discard_newline ; 丢弃第二次输入后的换行符(可选,若不需要可省略)

    call exit

; 读取一个字符到ecx指向的缓冲区
input:
    mov eax, 3          ; read系统调用号
    mov ebx, 0          ; stdin文件描述符
    mov edx, 1          ; 读取1个字节
    int 0x80
    ret

; 输出ecx指向的缓冲区中的一个字符
write:
    mov eax, 4          ; write系统调用号
    mov ebx, 1          ; stdout文件描述符
    mov edx, 1          ; 输出1个字节
    int 0x80
    ret

; 丢弃输入缓冲区中的换行符
discard_newline:
    mov ecx, temp_buffer
    mov eax, 3
    mov ebx, 0
    mov edx, 1
    int 0x80
    ; 检查是否是换行符,如果不是可以继续丢弃(处理多字符输入的情况)
    cmp byte [temp_buffer], 0x0A
    jne discard_newline
    ret

exit:
    mov eax, 1
    xor ebx, ebx
    int 0x80
    ret

额外说明

  • 如果你希望允许用户输入多个字符后只取第一个,discard_newline函数的循环逻辑可以确保清空输入缓冲区直到遇到换行符。
  • 编译运行命令:nasm -f elf32 your_program.asm -o your_program.o && ld -m elf_i386 your_program.o -o your_program && ./your_program

内容的提问来源于stack exchange,提问作者programmer with problems

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:35:12