汇编语言 文件管理
系统将任何输入或输出数据视为字节流。
有 3 种标准文件流:
- 标准输入(stdin)
- 标准输出(stdout)
- 标准错误(stderr)
文件描述符
文件描述符 是作为 文件id 分配给文件的 16 位整数。创建新文件或打开现有文件时,文件描述符用于访问文件。
标准文件流的文件描述符 -stdin
、stdout
和 stderr
分别为 0、1 和 2。
文件指针
文件指针 以字节为单位指定文件中后续读/写操作的位置。每个文件都被视为一个字节序列。每个打开的文件都与一个文件指针相关联,该指针指定相对于文件开头的偏移量(以字节为单位)。打开文件时,文件指针设置为 0。
文件处理系统调用
下表简要介绍了与文件处理相关的系统调用:
%eax | 名称 | %ebx | %ecx | %edx |
---|---|---|---|---|
2 | sys_fork | struct pt_regs | - | - |
3 | sys_read | unsigned int | char | size_t |
4 | sys_write | unsigned int | const char | size_t |
5 | sys_open | const char | int | int |
6 | sys_close | unsigned int | - | - |
8 | sys_creat | const char | int | - |
19 | sys_lseek | unsigned int | off_t | unsigned int |
使用系统调用所需的步骤与前面讨论的相同:
- 将系统呼叫号码放入 EAX 寄存器。
- 将系统调用的参数存储在寄存器 EBX、ECX 等中。
- 调用相关中断(80h)。
- 结果通常返回到 EAX 寄存器中。
创建和打开文件
要创建和打开文件,请执行以下任务:
- 将系统调用
sys_creat()
放入 EAX 寄存器中。 - 将文件名放入 EBX 寄存器。
- 将文件权限放入 ECX 寄存器。
系统调用返回 EAX 寄存器中创建的文件的文件描述符,如果出现错误,错误代码位于 EAX 寄存器。
打开现有文件
要打开现有文件,请执行以下任务:
- 将系统调用
sys_open()
放入 EAX 寄存器。 - 将文件名放入 EBX 寄存器。
- 将文件访问模式放入 ECX 寄存器。
- 将文件权限放入 EDX 寄存器。
系统调用返回 EAX 寄存器中创建的文件的文件描述符,如果出现错误,错误代码位于EAX寄存器。
在文件访问模式中,最常用的是:只读(0)、只写(1) 和 读写(2)。
从文件读取
要读取文件,请执行以下任务:
- 将系统调用
sys_read()
放入 EAX 寄存器中。 - 将文件描述符放入 EBX 寄存器。
- 将指针指向 ECX 寄存器中的输入缓冲区。
- 将缓冲区大小,即要读取的字节数,放入 EDX 寄存器。
系统调用返回在 EAX 寄存器中读取的字节数,如果出现错误,错误代码位于 EAX 寄存器。
写入文件
要写入文件,请执行以下任务:
- 将系统调用
sys_write()
放入 EAX 寄存器中。 - 将文件描述符放入 EBX 寄存器。
- 将指针指向 ECX 寄存器中的输出缓冲区。
- 将缓冲区大小,即要写入的字节数,放入 EDX 寄存器。
系统调用返回写入 EAX 寄存器的实际字节数,如果出现错误,错误代码位于 EAX 寄存器中。
关闭文件
要关闭文件,请执行以下任务:
- 将系统调用
sys_close()
放入 EAX 寄存器中。 - 将文件描述符放入 EBX 寄存器。
如果出现错误,系统调用将返回 EAX 寄存器中的错误代码。
更新文件
要更新文件,请执行以下任务−
- 将系统调用
sys_lseek()
放入 EAX 寄存器中。 - 将文件描述符放入 EBX 寄存器。
- 将偏移值放入 ECX 寄存器。
- 将偏移量的参考位置放入 EDX 寄存器。
参考位置可以是:
- 文件开头 - 值 0
- 当前位置 - 值 1
- 文件结尾 - 值 2
如果出现错误,系统调用将返回 EAX 寄存器中的错误代码。
实例
以下程序创建并打开名为 myfile.txt 的文件,并在此文件中写入文本 “Welcome to Cankaoshouce.com”。接下来,程序读取文件并将数据存储到名为 info
的缓冲区中。最后,它显示存储在 info
中的文本。
section .text
global _start ;必须声明才能使用 gcc
_start: ;告诉链接器入口点
; 创建文件
mov eax, 8
mov ebx, file_name
mov ecx, 0777 ;所有人的读、写和执行
int 0x80 ;调用内核
mov [fd_out], eax
; 写入文件
mov edx,len ;字节数
mov ecx, msg ;消息
mov ebx, [fd_out] ;文件描述
mov eax,4 ;系统调用号 (sys_write)
int 0x80 ;调用内核
; 关闭文件
mov eax, 6
mov ebx, [fd_out]
; 写入指示文件写入结束的消息
mov eax, 4
mov ebx, 1
mov ecx, msg_done
mov edx, len_done
int 0x80
; 打开文件进行读取
mov eax, 5
mov ebx, file_name
mov ecx, 0 ;用于只读访问
mov edx, 0777 ;所有人的读、写和执行
int 0x80
mov [fd_in], eax
; 读取文件
mov eax, 3
mov ebx, [fd_in]
mov ecx, info
mov edx, 26
int 0x80
; 关闭文件
mov eax, 6
mov ebx, [fd_in]
int 0x80
; 打印信息
mov eax, 4
mov ebx, 1
mov ecx, info
mov edx, 26
int 0x80
mov eax,1 ;系统调用号 (sys_exit)
int 0x80 ;调用内核
section .data
file_name db 'myfile.txt'
msg db 'Welcome to Cankaoshouce.com'
len equ $-msg
msg_done db 'Written to file', 0xa
len_done equ $-msg_done
section .bss
fd_out resb 1
fd_in resb 1
info resb 26
结果如下:
Written to file
Welcome to Cankaoshouce.com