Работа с файлами

Последнее обновление: 18.10.2023

Одной из часто встречающихся задач является работа с файлами. В Linux понятие файла довольно широко, и в данном случае мы будем работать с текстовыми файлами на диске. В языке Си для работы с файлами предназначена структура FILE и ряд функций. В контексте текущей статьи отметим следующие:

  • fopen: открывает файл и возвращает дескриптор для последующего взаимодействия с файлом

  • fclose: закрывает файл, получая его дескриптор

  • fputs: функция записи строки в файл

Я не буду подробно останавливаться на особенностях работы каждой функции, так как это больше относится к сфере программирования на языке Си. Лишь рассмотрим их вызов в коде на ассемблере:

global main     ; функция main - точка входа

extern fopen ; подключаем функцию fopen
extern fputs ; подключаем функцию fputs
extern fclose ; подключаем функцию fclose

section .data
filename db "myfile2.txt",0
openmode db "w", 0
message db "Hello METANIT.COM!", 10, 0

section .text
main:
    sub rsp, 8              ; выравнивание должно быть по 16 байтам

    ; Открываем файл для записи
    mov rdi, filename
    mov rsi, openmode
    call fopen

    ; сохраняем полученный дескриптор файла в стек
    mov qword [rsp], rax
    ; запись строки
    mov rdi, message     ; Первый параметр - строка форматирования
    mov rsi, [rsp]       ; Второй параметр - дексриптор файла
    call fputs

    ; Закрытие файла
    mov rdi, [rsp]
    call fclose

    add rsp, 8              ; восстанавливаем стек
    ret

Прежде всего в программе определено несколько глобальных переменных. Переменная filename указывает на имя файл, в который мы будем записывать данные:

filename db "myfile2.txt",0

Предполагается, что файл будет расположен в текущей папке (если его нет, он будет создан).

Переменная openmode указывает на режим доступа к файлу. Мы будем записывать в файл, поэтому в качестве режима применяется строка "w":

openmode db "w",0

Далее идет строка, которая будет записываться в файл:

message db "Hello METANIT.COM!", 10, 0

В программе выделяем 8 байт в стеке, с одной строны, обеспечивая место для хранения дескриптора файла, а с другой стороны, гарантируя обеспечение выравнивания по 16-байтной границе.

sub rsp, 8

Затем открываем файл функцией fopen():

mov rdi, filename
mov rsi, openmode
call fopen

Первый параметр функции - путь к файлу, а второй - режим открытия. В результате открытия в регистр rax помещается дескриптор файла.

Затем сохраняем дескриптор файла в стек (так как регистр rax далее будет изменяться) и записываем в файл строку:

; сохраняем полученный дескриптор файла в стек
mov qword [rsp], rax
; запись строки
mov rdi, message     ; Первый параметр - строка форматирования
mov rsi, [rsp]       ; Второй параметр - дексриптор файла
call fputs

Первый параметр функции fputs - строка для записи - глобальная переменная message, а второй параметр - дескриптор файла, в который будет идти запись.

После окончания работы нам надо закрыть файл с помощью функции fclose():

; Закрытие файла
mov rdi, [rsp]
call fclose

Функции передается дескриптор файла, ранее сохраненный в стек.

Допустим, программа находится в файле hello.asm. Сначала скомпилируем программу с помощью ассемблера NASM в объектный файл:

nasm -f elf64 hello.asm -o hello.o

Затем с помощью GCC соберем программу в исполняемый файл

gcc hello.о -static -o hello

После компиляции запустим приложение на выполнение, и в папке программы будет создан файл myfile2.txt, в который будет записана строка.

Аналогичный пример на Windows:

global main     ; функция main - точка входа

extern fopen ; подключаем функцию fopen
extern fputs ; подключаем функцию fputs
extern fclose ; подключаем функцию fclose

section .data
filename db "myfile2.txt",0
openmode db "w", 0
message db "Hello METANIT.COM!", 10, 0

section .text
main:
    sub rsp, 40              ; выравнивание должно быть по 16 байтам

    ; Открываем файл для записи
    mov rcx, filename
    mov rdx, openmode
    call fopen

    ; сохраняем полученный дескриптор файла в стек
    mov qword [rsp], rax
    ; запись строки
    mov rcx, message     ; Первый параметр - строка форматирования
    mov rdx, [rsp]       ; Второй параметр - дексриптор файла
    call fputs

    ; Закрытие файла
    mov rcx, [rsp]
    call fclose

    add rsp, 40              ; восстанавливаем стек
    ret
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850