x86 汇编入门(02):读取用户输入
上一篇程序只会「说」,不会「听」。真实程序几乎都要处理输入——命令行参数、用户键入、网络数据,本质都是往缓冲区里塞字节。这一篇我们学 sys_read,并认识汇编里的第三个地盘:.bss 段。
这是「x86 汇编入门」系列的第 2 篇。上一篇用
sys_write输出了 Hello World。这一篇通过02_input.asm,实现读取键盘输入并回显。
一、三段式内存布局
到本篇为止,汇编程序的「地盘」凑齐了:
| 段 | 用途 | 类比 |
|---|---|---|
.data |
已初始化的常量(字符串、数字) | 写死在程序里的便签 |
.bss |
未初始化的变量(缓冲区) | 运行时用的空白草稿纸 |
.text |
可执行指令 | 操作步骤 |
.bss 里的空间在程序加载时自动清零,用 resb N 预留 N 个字节:
1 | section .bss |
二、sys_read 怎么用?
sys_read 是 sys_write 的镜像操作:
| 寄存器 | 含义 |
|---|---|
rax |
0(调用号) |
rdi |
文件描述符(0 = stdin) |
rsi |
缓冲区地址 |
rdx |
最多读取的字节数 |
返回值 rax |
实际读到的字节数 |
注意:用户按回车后,读到的内容包含换行符。
三、程序流程
02_input.asm 做三件事:
- 打印提示
请输入你的名字: - 从 stdin 读入最多 64 字节到
name_buf - 打印
你好,+ 用户输入
核心代码片段:
1 | ; 输出提示 |
四、为什么要保存 rax?
syscall 返回后,rax 里是读到的字节数。但下一次 sys_write 又会把 rax 改成 1。所以读到长度后要立刻存到 r12 这种不会被 syscall 乱改的寄存器里。
这里顺带引出 x86_64 的一个约定:
syscall会破坏rax、rcx、r11r12–r15、rbx、rbp是 callee-saved,适合当长期变量
后面循环、函数篇会反复用到这个区别。
五、运行示例
1 | make |
交互:
1 | 请输入你的名字: Alex |
六、小结
本篇要点:
.bss段用resb声明缓冲区sys_read从 fd 读数据,返回值是实际字节数- 输出用户输入时要用实际长度,不能写死缓冲区大小
- 用 callee-saved 寄存器保存 syscall 的返回值
x86 汇编入门系列第 2 篇完。下一篇进入算术运算——寄存器里做加减乘除,并把数字转成能打印的 ASCII 字符串。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 WALL-E`s Blog!







