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

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

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

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

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

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

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

.globl main

.data
filename: .asciz "myfile.txt"
openmode: .asciz "w"
message: .asciz "Hello METANIT.COM!\n"

.text
main:
    subq $8, %rsp

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

    # сохраняем полученный дескриптор файла в стек
    movq %rax, (%rsp)
    # запись строки
    movq $message, %rdi     # Первый параметр - строка форматирования
    movq (%rsp), %rsi       # Второй параметр - дексриптор файла
    call fputs

    # Закрытие файла
    movq (%rsp), %rdi
    call fclose

    addq $8, %rsp
    ret

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

filename: .asciz "myfile.txt"

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

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

openmode: .asciz "w"

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

message: .asciz "Hello METANIT.COM!\n"

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

subq $8, %rsp

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

movq $filename, %rdi
movq $openmode, %rsi
call fopen

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

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

# сохраняем полученный дескриптор файла в стек
movq %rax, (%rsp)
# запись строки
movq $message, %rdi     # Первый параметр - строка форматирования
movq (%rsp), %rsi       # Второй параметр - дексриптор файла
call fputs

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

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

# Закрытие файла
movq (%rsp), %rdi
call fclose

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

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

gcc hello.s -static -o hello

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850