程序不能只跟终端打交道。配置文件、日志、数据文件——都离不开文件 I/O。这一篇用 06_file_io.asm 完成「写入 → 关闭 → 重新打开 → 读取 → 输出」全流程,也是本系列的收官之作。

这是「x86 汇编入门」系列的第 6 篇,也是最后一篇。前五篇覆盖了输出、输入、算术、循环和函数。这一篇综合运用文件相关系统调用,并回顾整个系列的学习路径。

一、文件相关系统调用

调用号 名称 作用
2 sys_open 打开或创建文件
0 sys_read 从 fd 读取
1 sys_write 向 fd 写入
3 sys_close 关闭 fd

sys_open 参数:

寄存器 含义
rdi 文件路径(以 \0 结尾的 C 字符串)
rsi 打开标志 flags
rdx 权限 mode(创建文件时有效)
返回值 rax 文件描述符;失败时为负数

常用 flags(可位或组合):

标志 含义
O_RDONLY 0 只读
O_WRONLY 1 只写
O_CREAT 0x40 不存在则创建
O_TRUNC 0x200 截断(清空)

写入模式组合:O_WRONLY | O_CREAT | O_TRUNC = 0x241

二、程序流程

06_file_io.asm 分三步:

第一步:创建并写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mov     rax, 2
mov rdi, filepath
mov rsi, O_WR_CREAT_TRUNC ; 0x241
mov rdx, 0644o ; rw-r--r--,'o' 表示八进制
syscall

mov [fd], rax ; 保存 fd

mov rax, 1 ; sys_write
mov rdi, [fd]
mov rsi, write_msg
mov rdx, write_len
syscall

mov rax, 3 ; sys_close
mov rdi, [fd]
syscall

第二步:只读打开并读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mov     rax, 2
mov rdi, filepath
mov rsi, 0 ; O_RDONLY
mov rdx, 0
syscall

mov [fd], rax

mov rax, 0 ; sys_read
mov rdi, [fd]
mov rsi, read_buf
mov rdx, 256
syscall

mov r12, rax ; 保存读取长度

mov rax, 3
mov rdi, [fd]
syscall

第三步:把读到的内容打印到 stdout

1
2
3
4
5
mov     rax, 1
mov rdi, 1
mov rsi, read_buf
mov rdx, r12
syscall

三、错误处理

打开文件失败时,rax 为负数。程序用 test rax, rax + js .error 检测符号位:

1
2
3
4
.error:
mov rax, 60
mov rdi, 1 ; 以状态码 1 退出
syscall

生产级代码还会打印 errno,入门 demo 保持简洁。

四、运行输出

1
2
make
./build/06_file_io
1
2
[写入] 数据已写入 /tmp/asm_test.txt
[读取] 文件内容: This file was created by an assembly program!

文件在容器内的 /tmp/asm_test.txt,可以 cat 验证。

五、系列回顾

主题 核心技能
00 环境搭建 Docker、nasm、ld、make
01 Hello World section、syscall、sys_write / sys_exit
02 用户输入 sys_read、.bss、缓冲区
03 算术运算 add/sub/imul/idiv、数字转字符串
04 循环 cmp、条件跳转、jmp
05 函数 call/ret、栈帧、递归
06 文件 I/O sys_open/read/write/close

从 20 行 Hello World 到读写磁盘文件,你没有借助 printf、没有链接 libc,每一行都是自己和内核的直接对话。

六、可以继续往哪走?

  • 调试:gdb 单步、查看寄存器和栈;strace 跟踪系统调用
  • 更多 syscall:目录操作、内存映射(mmap)、网络 socket
  • 和 C 互调:汇编写性能关键路径,C 写业务逻辑
  • 对照学习:用 gcc -S 看 C 编译出的汇编,理解编译器怎么做函数调用和循环

七、小结

本篇完成了文件创建、写入、读取、关闭的完整流程,并串联了系列全部知识点。汇编入门最难的是迈出第一步——如果你跟着系列走到了这里,已经比大多数人更靠近机器的真相。

x86 汇编入门系列全部 7 篇完。感谢阅读,去写你自己的第一条 syscall 吧。