汇编 - 文件管理
系统将任何输入或输出数据视为字节流。存在三个标准文件流:
- 标准输入 (stdin),
- 标准输出 (stdout), 和
- 标准错误 (stderr).
文件描述符
文件描述符是一个分配给文件的16位整数,作为文件的ID。当创建一个新文件或打开一个现有文件时,文件描述符用于访问该文件。
标准文件流stdin,stdout和stderr的文件描述符分别为0、1和2。
文件指针
文件指针以字节为单位指定文件中后续读/写操作的位置。每个文件都被视为字节序列。每个打开的文件都与一个文件指针相关联,该文件指针指定相对于文件开头的字节偏移量。打开文件时,文件指针设置为零。
文件处理系统调用
下表简要描述了与文件处理相关的系统调用:
%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()编号8放入EAX寄存器。
- 将文件名放入EBX寄存器。
- 将文件权限放入ECX寄存器。
系统调用在EAX寄存器中返回已创建文件的描述符,如果出错,则EAX寄存器中为错误代码。
打开现有文件
要打开现有文件,请执行以下任务:
- 将系统调用sys_open()编号5放入EAX寄存器。
- 将文件名放入EBX寄存器。
- 将文件访问模式放入ECX寄存器。
- 将文件权限放入EDX寄存器。
系统调用在EAX寄存器中返回已创建文件的描述符,如果出错,则EAX寄存器中为错误代码。
在文件访问模式中,最常用的是:只读(0)、只写(1)和读写(2)。
从文件读取
要从文件读取,请执行以下任务:
将系统调用sys_read()编号3放入EAX寄存器。
将文件描述符放入EBX寄存器。
将指向输入缓冲区的指针放入ECX寄存器。
将缓冲区大小(即要读取的字节数)放入EDX寄存器。
系统调用在EAX寄存器中返回读取的字节数,如果出错,则EAX寄存器中为错误代码。
写入文件
要写入文件,请执行以下任务:
将系统调用sys_write()编号4放入EAX寄存器。
将文件描述符放入EBX寄存器。
将指向输出缓冲区的指针放入ECX寄存器。
将缓冲区大小(即要写入的字节数)放入EDX寄存器。
系统调用在EAX寄存器中返回实际写入的字节数,如果出错,则EAX寄存器中为错误代码。
关闭文件
要关闭文件,请执行以下任务:
- 将系统调用sys_close()编号6放入EAX寄存器。
- 将文件描述符放入EBX寄存器。
系统调用返回,如果出错,则EAX寄存器中为错误代码。
更新文件
要更新文件,请执行以下任务:
- 将系统调用sys_lseek()编号19放入EAX寄存器。
- 将文件描述符放入EBX寄存器。
- 将偏移值放入ECX寄存器。
- 将偏移量的参考位置放入EDX寄存器。
参考位置可以是
- 文件开头 - 值0
- 当前位置 - 值1
- 文件结尾 - 值2
系统调用返回,如果出错,则EAX寄存器中为错误代码。
示例
下面的程序创建一个名为myfile.txt的文件并打开它,然后在这个文件中写入文本“欢迎来到 Tutorials Point”。接下来,程序从文件中读取数据并将其存储到名为info的缓冲区中。最后,它显示存储在info中的文本。
section .text global _start ;must be declared for using gcc _start: ;tell linker entry point ;create the file mov eax, 8 mov ebx, file_name mov ecx, 0777 ;read, write and execute by all int 0x80 ;call kernel mov [fd_out], eax ; write into the file mov edx,len ;number of bytes mov ecx, msg ;message to write mov ebx, [fd_out] ;file descriptor mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel ; close the file mov eax, 6 mov ebx, [fd_out] ; write the message indicating end of file write mov eax, 4 mov ebx, 1 mov ecx, msg_done mov edx, len_done int 0x80 ;open the file for reading mov eax, 5 mov ebx, file_name mov ecx, 0 ;for read only access mov edx, 0777 ;read, write and execute by all int 0x80 mov [fd_in], eax ;read from file mov eax, 3 mov ebx, [fd_in] mov ecx, info mov edx, 26 int 0x80 ; close the file mov eax, 6 mov ebx, [fd_in] int 0x80 ; print the info mov eax, 4 mov ebx, 1 mov ecx, info mov edx, 26 int 0x80 mov eax,1 ;system call number (sys_exit) int 0x80 ;call kernel section .data file_name db 'myfile.txt' msg db 'Welcome to Tutorials Point' 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 Tutorials Point