x86汇编:如何将rax返回值存入寄存器供后续使用?及存储至r8后无法打印输入字符串的问题排查
解决x86汇编中无法正确打印用户输入字符串的问题
嘿,咱们一步步来解决这个问题——你其实已经很接近了,只是几个小错误拖了后腿!
首先找出代码里的两个关键错误
- 错误的文件描述符:你在执行
sys_read(系统调用号0)的时候,把rdi设成了1,但1是标准输出(stdout)的文件描述符,读取用户输入应该用标准输入(stdin),也就是0。这个错误会导致sys_read调用失败,rax里返回的是错误码(比如-EBADF),而不是你期望的读取字节数。 - 多余的
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
相关产品推荐
相关产品推荐

