汇编语言文件管理.md

原始源文件

---
ingested: true
ingestedAt: 2026-05-17
---
标题: 汇编语言 - 文件管理
链接: https://www.runoob.com/assembly/assembly-file.html
内容: 文件管理是程序与外部存储交互的基础。

通过系统调用,汇编程序可以打开、读取、写入和关闭文件,与高级语言一样灵活地处理文件 IO。

---

## 文件操作流程总览

文件操作遵循打开→读写→关闭的基本流程,以及三个标准文件描述符:

![文件操作流程图](https://www.runoob.com/wp-content/uploads/2026/04/file-io-flow.svg)

---

## 文件操作相关的系统调用

| 系统调用        | 调用号 | 用途        | 主要参数                     |
| ----------- | --- | --------- | ------------------------ |
| sys_open   | 5   | 打开/创建文件   | EBX=文件名, ECX=标志, EDX=权限  |
| sys_read   | 3   | 读取文件      | EBX=fd, ECX=缓冲区, EDX=字节数 |
| sys_write  | 4   | 写入文件      | EBX=fd, ECX=缓冲区, EDX=字节数 |
| sys_close  | 6   | 关闭文件      | EBX=fd                   |
| sys_creat  | 8   | 创建文件(旧方式) | EBX=文件名, ECX=权限          |
| sys_lseek  | 19  | 移动文件指针    | EBX=fd, ECX=偏移, EDX=起始位置 |
| sys_unlink | 10  | 删除文件      | EBX=文件名                  |

---

## 文件打开标志

| 常量        | 值           | 说明        |
| --------- | ----------- | --------- |
| O_RDONLY | 0           | 只读        |
| O_WRONLY | 1           | 只写        |
| O_RDWR   | 2           | 读写        |
| O_CREAT  | 64(0x40)    | 若文件不存在则创建 |
| O_TRUNC  | 512(0x200)  | 打开时清空文件内容 |
| O_APPEND | 1024(0x400) | 追加到文件末尾   |

多个标志用 OR 组合,例如 `O_WRONLY | O_CREAT | O_TRUNC = 1 | 64 | 512 = 577`

---

## 创建并写入文件

## 实例

; 文件路径:file_write.asm  
; 创建文件并写入内容

section .data  
 filename db 'runoob_output.txt', 0 ; 文件名(null 结尾)  
 content db 'Hello, RUNOOB!', 0xA ; 要写入的内容  
 content_len equ $ - content  
 create_msg db 'File created successfully!', 0xA  
 create_msg_len equ $ - create_msg

section .bss  
 fd resd 1 ; 文件描述符

section .text  
global _start

_start:  
; 1. 创建文件  
mov eax, 8 ; sys_creat  
mov ebx, filename ; 文件名  
mov ecx, 0o644 ; 权限:rw-r--r--  
; 0o644 = 所有者读写、组只读、其他只读  
int 0x80

mov [fd], eax ; 保存文件描述符

; 2. 写入内容到文件  
mov eax, 4 ; sys_write  
mov ebx, [fd] ; 文件描述符  
mov ecx, content ; 数据地址  
mov edx, content_len ; 数据长度  
int 0x80

; 3. 关闭文件  
mov eax, 6 ; sys_close  
mov ebx, [fd] ; 文件描述符  
int 0x80

; 4. 提示成功  
mov eax, 4  
mov ebx, 1  
mov ecx, create_msg  
mov edx, create_msg_len  
int 0x80

mov eax, 1  
mov ebx, 0  
int 0x80  

运行结果:

$ nasm -f elf32 file_write.asm -o file_write.o
$ ld -m elf_i386 file_write.o -o file_write
$ ./file_write
File created successfully!
$ cat runoob_output.txt
Hello, RUNOOB!

---

## 读取文件内容

## 实例

; 文件路径:file_read.asm  
; 打开并读取文件内容

section .data  
 filename db 'runoob_output.txt', 0  
 open_error db 'Error: cannot open file', 0xA  
 open_error_len equ $ - open_error  
 read_success db 'File content:', 0xA  
 read_success_len equ $ - read_success

section .bss  
 fd resd 1  
 buffer resb 1024 ; 读取缓冲区

section .text  
global _start

_start:  
; 1. 打开文件(只读)  
mov eax, 5 ; sys_open  
mov ebx, filename ; 文件名  
mov ecx, 0 ; 只读模式  
mov edx, 0 ; 权限(只读时忽略)  
int 0x80

cmp eax, 0 ; 文件描述符 < 0 表示错误  
jl open_failed

mov [fd], eax ; 保存文件描述符

; 2. 读取文件内容  
mov eax, 3 ; sys_read  
mov ebx, [fd] ; 文件描述符  
mov ecx, buffer ; 缓冲区  
mov edx, 1024 ; 最多读取 1024 字节  
int 0x80  
; 返回值 eax = 实际读取的字节数  
mov esi, eax ; 保存读取字节数

; 3. 关闭文件  
mov eax, 6 ; sys_close  
mov ebx, [fd]  
int 0x80

; 4. 输出提示信息  
mov eax, 4  
mov ebx, 1  
mov ecx, read_success  
mov edx, read_success_len  
int 0x80

; 5. 输出文件内容到屏幕  
mov eax, 4  
mov ebx, 1  
mov ecx, buffer  
mov edx, esi ; 使用实际读取的字节数  
int 0x80  
jmp exit

open_failed:  
mov eax, 4  
mov ebx, 1  
mov ecx, open_error  
mov edx, open_error_len  
int 0x80

exit:  
mov eax, 1  
mov ebx, 0  
int 0x80  

运行结果:

$ nasm -f elf32 file_read.asm -o file_read.o
$ ld -m elf_i386 file_read.o -o file_read
$ ./file_read
File content:
Hello, RUNOOB!

---

## 追加写入文件

## 实例

; 文件路径:file_append.asm  
; 以追加模式打开文件并写入

section .data  
 filename db 'runoob_log.txt', 0  
 log_entry db '[INFO] Program executed successfully.', 0xA  
 log_len equ $ - log_entry

section .bss  
 fd resd 1

section .text  
global _start

_start:  
; 打开文件(创建 + 追加模式)  
mov eax, 5 ; sys_open  
mov ebx, filename ; 文件名  
mov ecx, 0x441 ; O_WRONLY | O_CREAT | O_APPEND  
; O_WRONLY=1, O_CREAT=0x40, O_APPEND=0x400  
; 组合:1 | 0x40 | 0x400 = 0x441  
mov edx, 0o644 ; 创建时的权限  
int 0x80

mov [fd], eax

; 追加写入  
mov eax, 4 ; sys_write  
mov ebx, [fd] ; 文件描述符  
mov ecx, log_entry ; 日志内容  
mov edx, log_len  
int 0x80

; 关闭文件  
mov eax, 6  
mov ebx, [fd]  
int 0x80

mov eax, 1  
mov ebx, 0  
int 0x80  

---

## 复制文件

一个综合示例:将一个文件的内容复制到另一个文件:

## 实例

; 文件路径:file_copy.asm  
; 复制文件:将 runoob_input.txt 复制到 runoob_copy.txt

section .data  
 src_file db 'runoob_input.txt', 0  
 dst_file db 'runoob_copy.txt', 0  
 success_msg db 'File copied successfully!', 0xA  
 success_len equ $ - success_msg  
 error_msg db 'Error during file copy', 0xA  
 error_len equ $ - error_msg

section .bss  
 src_fd resd 1  
 dst_fd resd 1  
 buffer resb 4096 ; 4KB 复制缓冲区

section .text  
global _start

_start:  
; 1. 打开源文件(只读)  
mov eax, 5  
mov ebx, src_file  
mov ecx, 0 ; O_RDONLY  
mov edx, 0  
int 0x80  
cmp eax, 0  
jl error_exit  
mov [src_fd], eax

; 2. 创建目标文件  
mov eax, 8 ; sys_creat  
mov ebx, dst_file  
mov ecx, 0o644  
int 0x80  
cmp eax, 0  
jl error_exit  
mov [dst_fd], eax

copy_loop:  
; 3. 从源文件读取  
mov eax, 3 ; sys_read  
mov ebx, [src_fd]  
mov ecx, buffer  
mov edx, 4096  
int 0x80  
; eax = 实际读取的字节数  
cmp eax, 0 ; 读到 0 字节?  
jle copy_done ; 是,文件结束

; 4. 写入目标文件  
mov esi, eax ; 保存读取的字节数  
mov eax, 4 ; sys_write  
mov ebx, [dst_fd]  
mov ecx, buffer  
mov edx, esi ; 写入实际读取的字节数  
int 0x80  
jmp copy_loop ; 继续循环

copy_done:  
; 5. 关闭文件  
mov eax, 6 ; sys_close  
mov ebx, [src_fd]  
int 0x80

mov eax, 6  
mov ebx, [dst_fd]  
int 0x80

; 6. 输出成功信息  
mov eax, 4  
mov ebx, 1  
mov ecx, success_msg  
mov edx, success_len  
int 0x80  
jmp exit

error_exit:  
mov eax, 4  
mov ebx, 1  
mov ecx, error_msg  
mov edx, error_len  
int 0x80

exit:  
mov eax, 1  
mov ebx, 0  
int 0x80  

> 文件操作前后务必检查系统调用的返回值(在 EAX 中)。负值表示错误(如 -2 是 ENOENT 文件不存在,-13 是 EACCES 权限不足),忽略错误返回值是文件操作 bug 的最大来源。