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

x86-64 Linux汇编程序二次读取用户输入失效问题

x86-64 Linux汇编程序读取输入问题排查

我开发的x86-64架构Linux汇编程序中,首次读取用户输入的syscall执行正常,但在后续的_cels和_fahr分支中调用read系统调用读取温度值时,程序未等待用户输入就直接跳转回_start,无法获取温度输入。已在代码中标注出两个问题区域,并添加jmp _start语句用于调试,代码如下:

bits 64

global  _start

section .text
  _start: 
    ;Setting
    mov          rax, 1
    mov          rsi, unit
    mov          rdx, unitlen
    syscall

    mov          rax, 0
    mov          rsi, unitre ; assigns unitre in memory
    mov          rdx, 1
    syscall

    mov        al, [unitre] ; gets the value of the first character through pointing at unitre 
                            ; which is the first pointer of the string 
    cmp          al, 'q'
    je           exit

    cmp          al, 'c'
    je           _cels

    cmp          al, 'f'
    je           _fahr

    jmp exit

  _cels:
    mov          rax, 1
    mov          rdi, 1
    mov          rsi, numC
    mov          rdx, numClen
    syscall

    ; Problem area pt. 1
    mov          rax, 0
    mov          rdi, 1
    mov          rsi, numre
    mov          rdx, 1
    ;int 0x80

    jmp        _start
    ;convert numre to degrees fahrenheit
    mov          rax, [numre]
    imul         rax, 9
    mov          rbx, 5
    idiv         rbx
    add          rax, 32

    mov          rax, 1
    mov          rdi, 1
    mov          rsi, numre
    mov          rdx, numrelen
    syscall

    mov          rsi, deg
    mov          rdi, 1
    mov          rdx, degl
    syscall

    ;jmp        _start
  _fahr:
    mov          rax, 1
    mov          rdi, 1
    mov          rsi, numF
    mov          rdx, numFlen
    syscall

    ; Problem area pt. 2
    mov          rax, 0
    mov          rdi, 1
    mov          rsi, numre
    mov          rdx, numrelen
    syscall

    jmp        _start

    ; Convert numre to degrees celsius
    mov          rax, [numre]
    sub          rax, 32
    imul         rax, 5
    mov          rbx, 9
    idiv         rbx

    mov          rax, 1
    mov          rdi, 1
    mov          rsi, numre
    mov          rdx, numrelen
    syscall

    mov          rsi, deg
    mov          rdi, 1
    mov          rdx, degl
    syscall

    ;jmp         _start
  exit:
    ;Exits program
    mov          rax, 60
    xor          rdi, rdi
    syscall

section   .data
  ;Conversion
  unit:      db      "Unit ('c' for Celsius or 'f' for Fahrenheit): ", 10
  unitlen:      equ      $      -      unit
  unitre:      db      "", 10
  numC:      db      "Degrees(C): ", 10
  numClen:      equ      $      -      numC
  numF:      db      "Degrees(F): ", 10
  numFlen:      equ      $      -      numF
  numre:      db      "", 0
  numrelen:      equ      $      -      numre
  deg:        db        "degrees", 10
  degl:      equ      $      -      deg

  ;testing
  num1      db      1

我的目标是实现摄氏温度与华氏温度的转换,但目前无法获取用户输入的温度值,请求帮助排查问题。


问题排查与修复建议

核心问题点

  • read系统调用的文件描述符错误:x86-64架构下,read系统调用(rax=0)的第一个参数rdi需要传入文件描述符,标准输入的文件描述符是0,但代码中错误地使用了1(标准输出),导致读取操作无效,无法获取用户输入。
  • 调试跳转语句直接跳过读取逻辑:_cels和_fahr分支中,read调用后立刻执行jmp _start,直接跳回程序入口,程序根本没有机会等待用户输入完成,也无法执行后续的转换逻辑。
  • 输入缓冲区容量不足:numre仅定义了1字节的存储空间(db "",0),无法容纳多位数字的温度值,且numrelen计算结果为1,限制了读取长度,无法获取完整的输入。
  • 未处理输入残留的换行符:首次读取单位时,用户输入字符后按回车,回车的换行符会留在输入缓冲区中,后续read调用会直接读取这个换行符,导致程序误判为用户输入完成。

修复步骤

  1. 修正read调用的文件描述符:将两个问题区域中的mov rdi, 1改为mov rdi, 0,指向标准输入。
  2. 移除调试用的跳转语句:删除_cels和_fahr分支中read调用后的jmp _start,让程序执行完读取、转换和输出逻辑。
  3. 扩大输入缓冲区:修改.data段中的numre定义为足够容纳多位数字的空间,例如:
    numre:      db      10 dup(0)  ; 预留10字节空间存储输入
    numrelen:   equ     $ - numre
    
  4. 处理输入残留的换行符:在首次读取单位后,添加额外的read调用读取并丢弃输入缓冲区中的换行符,避免影响后续温度值的读取。
  5. 完善数值转换逻辑:当前代码直接对numre中的ASCII字符进行运算,需要先将ASCII字符转换为数值(例如将'5'转换为5),运算完成后再将数值转换回ASCII字符输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:06:04