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

x86汇编:如何将rax返回值存入寄存器供后续使用?及存储至r8后无法打印输入字符串的问题排查

解决x86汇编中无法正确打印用户输入字符串的问题

嘿,咱们一步步来解决这个问题——你其实已经很接近了,只是几个小错误拖了后腿!

首先找出代码里的两个关键错误

  1. 错误的文件描述符:你在执行sys_read(系统调用号0)的时候,把rdi设成了1,但1是标准输出(stdout)的文件描述符,读取用户输入应该用标准输入(stdin),也就是0。这个错误会导致sys_read调用失败,rax里返回的是错误码(比如-EBADF),而不是你期望的读取字节数。
  2. 多余的syscall:在把rax的值存入r8之后,你多写了一次syscall。这个多余的调用会执行当前rax里的数值对应的系统调用(如果之前sys_read失败,rax是负数,这会触发错误),而且不管怎样,这个调用都会覆盖rax甚至破坏寄存器状态,导致你存在r8里的数值也可能失效。

关于rax里的内容

当sys_read调用成功时,rax返回的是实际读取的字节数(一个整数)——比如你输入Alice再加回车,总共是6个字节,rax就会是6。如果调用失败,rax会返回负数形式的错误码(比如文件描述符无效时返回-9)。

修正后的完整代码

section .data ; we're not allowed to edit anything ; in section .data for this assignment
prompt: db "What is your name? "
prompt_len: equ $-prompt
buffer: times 255 db '!'
resp1: db "Hello, "
resp1_len: equ $-resp1
resp2: db ", nice to meet you!", 10
resp2_len: equ $-resp2

section .text
global _start
_start:
; 打印提示语
mov rax, 1
mov rdi, 1
mov rsi, prompt
mov rdx, prompt_len
syscall

; 读取用户输入(修正后的关键部分)
mov rax, 0          ; sys_read的系统调用号
mov rdi, 0          ; 标准输入stdin的文件描述符是0
mov rsi, buffer     ; 输入内容将存储到这个缓冲区
mov rdx, 255        ; 缓冲区大小和上面的times 255对应(你之前写的225是笔误)
syscall

mov r8, rax         ; 保存读取到的字节数到r8,这里没有多余的syscall!
; 可选:如果不想打印输入末尾的换行符,取消下面这行注释
; sub r8, 1

; 打印"Hello, "
mov rax, 1
mov rdi, 1
mov rsi, resp1
mov rdx, resp1_len
syscall

; 打印用户输入的名字
mov rax, 1
mov rdi, 1
mov rsi, buffer
mov rdx, r8         ; 使用之前保存的r8作为输出长度
syscall

; 打印后续问候语
mov rax, 1
mov rdi, 1
mov rsi, resp2
mov rdx, resp2_len
syscall

; 退出程序
mov rax, 60
mov rdi, 0
syscall

额外小提示

用户输入的字符串末尾会自带一个换行符(因为你按下了回车),如果不想让名字后面多一个空行,可以在mov r8, rax之后加一行sub r8, 1,这样输出的时候就会去掉那个换行符。

现在运行这个修正后的代码,输入名字后就能得到你预期的输出啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 12:32:31