汇编语言 文件管理

  • 文件管理

    系统将任何输入或输出数据视为字节流。有三个标准文件流-
    • 标准输入(stdin)
    • 标准输出(stdout)
    • 标准错误(stderr)
  • 文件描述符

    文件描述符是分配给一个文件作为文件ID的16位整数。创建新文件或打开现有文件时,文件描述符用于访问文件。
    标准文件流的文件描述符-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的文件,并在该文件中写入文本“Welcome to Jc2182”。接下来,程序从文件读取并将数据存储到名为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 Jc2182'
    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 Jc2182