装配体-文件管理
系统将任何输入或输出数据视为字节流。有三个标准文件流 -
- 标准输入(stdin),
 - 标准输出(stdout),以及
 - 标准错误(stderr)。
 
文件描述符
文件描述符是一个 16 位整数,作为文件 id 分配给文件。当创建新文件或打开现有文件时,文件描述符用于访问文件。
标准文件流的文件描述符 - stdin、stdout和stderr分别为 0、1 和 2。
文件指针
文件指针以字节为单位指定文件中后续读/写操作的位置。每个文件被视为一个字节序列。每个打开的文件都与一个文件指针相关联,该文件指针指定相对于文件开头的偏移量(以字节为单位)。打开文件时,文件指针设置为零。
文件处理系统调用
下表简要描述了与文件处理相关的系统调用 -
| %eax | 姓名 | %ebx | %ecx | %edx | 
|---|---|---|---|---|
| 2 | 系统分叉 | 结构体pt_regs | - | - | 
| 3 | 系统读取 | 无符号整数 | 字符* | 尺寸_t | 
| 4 | 系统写入 | 无符号整数 | 常量字符* | 尺寸_t | 
| 5 | 系统打开 | 常量字符* | 整数 | 整数 | 
| 6 | 系统关闭 | 无符号整数 | - | - | 
| 8 | 系统创建 | 常量字符* | 整数 | - | 
| 19 | sys_lseek | 无符号整数 | 关闭_t | 无符号整数 | 
正如我们之前讨论的,使用系统调用所需的步骤是相同的 -
- 将系统调用号放入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的文件,并在此文件中写入文本“欢迎来到教程点”。接下来,程序从文件中读取数据并将数据存储到名为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