Skip to content

Latest commit

 

History

History
121 lines (71 loc) · 11.5 KB

lab08files.textile

File metadata and controls

121 lines (71 loc) · 11.5 KB

Лабораторная работа №7. Изучение строковых инструкций. Работа с файлами

Краткие теоретические сведения

Строковый примитив поиска

Для поиска определенного символа или слова в строке используют примитив scas. Значение для поиска задается в регистре eax. Адрес строки определяется адресом в edi.

Префикс повторения строкового примитива

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

  • repe, repz — повторять пока совпадает;
  • repne, repnz — повторять пока не совпадает.
mov     ecx, 100   ; размер строки
         mov     eax, 1234h
         mov     edi, Buff  ; ее адрес
         repne   scasw      ; ищем слово 1234h

Число повторений строкового примитива определяется значением в регистре ecx либо исходом поиска.

Строковый примитив сравнения строк

Для сравнения двух строк используют примитив cmps. При этом esi указывает на одну строку, а edi на другую. Как и для scas, тут применяют два префикса повторения repe и repne — для первого несовпадения или совпадения соответственно.

mov  ecx, 100
       mov  esi, Str1
       mov  edi, Str2
       repe cmpsb   ; сравнивать, пока совпадают
       jne  NotEq   ; различны

Примитив cmps устанавливает те же флаги, что и инструкция cmp. Поэтому строки можно сравнивать не только на равенство или неравенство. Но при необходимости более сложного сравнения нужно использовать циклы.

mov  ecx, 100
       mov  esi, Str1
       mov  edi, Str2
  @@1: cmpsb
       jg   S1GT      ; байт si-строки больше байта di-строки
       loop @@1

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

Для открытия существующего файла или создания нового используют функцию open (системный вызов номер 5). В синтаксисе Си она выглядит следующим образом:

int open (const char *filename, int flags[, mode_t mode])

Функция open создает и возвращает новый дескриптор для указанного файла. Индикатор текущей позиции при этом находится в начале файла. Функция может иметь переменный набор аргументов; аргумент mode используется только при создании файла и задает права доступа к нему (в стандартном для UNIX-систем числовом виде, например восьмеричным числом из трех цифр).

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

Примечание: Имя файла должно быть задано в виде классической ASCIIZ-строки. Поэтому при вводе имени файла с клавиатуры необходимо обеспечить, чтобы в конце введенной строки находится нуль-терминатор, а не символ \n.

Аргумент flags задает режим открытия файла. Это — битовая маска; вы создаете значение поразрядным ИЛИ соответствующих параметров. Аргумент flags должен обязательно включать одно из этих значений, для задания режима доступа к файлу:

O_RDONLY=0 Открывает файл для чтения.
O_WRONLY=1 Открывает файл для записи.
O_RDWR=2 Открывает файл и для чтения и для записи.

Аргумент flags может также включать любую комбинацию следующих флагов:

lp11cm

O_APPEND=2000 & Если установлен, то все операции записи запишут данные в конец файла, расширяя его, независимо от текущей файловой позиции.
O_CREAT=100 & Если установлен, будет создан файл, если он еще не существует.
O_EXCL=200 & Если и O_CREAT и O_EXCL установлены, то open выдает ошибку, если заданный файл уже существует.
O_NOCTTY=400 & Если filename — имя терминала, не делайте его терминалом управления для процесса.
O_NONBLOCK=4000 & Устанавливает режим неблокирования. Эта опция обычно полезна для специальных файлов FIFO и устройств типа терминалов. Обычно, для этих файлов open блокируется, пока файл не готов. Если O_NONBLOCK установлен, open возвращается немедленно. O_NONBLOCK-бит также воздействует на чтение и на запись: он разрешает им возвращаться немедленно с состоянием ошибки, если не имеется никакого доступного ввода, или если вывод не может быть записан.
O_TRUNC=1000 & Если файл существует и открыт для записи, он усекается до нулевой длины. Эта опция полезна только для регулярных файлов, а не специальных файлов типа каталогов или FIFO.

Файл /usr/include/fcntl.h содержит более подробную информацию о значениях флагов.

Нормальное возвращаемое значение open — неотрицательное целое число, равное дескриптору файла. В случае ошибки возвращается значение -1.

Закрытие файла выполняется функцией close (системный вызов номер 6):

int close (int filedes)

Функция закрывает дескриптор файла filedes. Закрытие файла имеет следующие последствия:

  • Описатель файла освобожден.
  • Любые блокировки записи, принадлежащие процессу на файле, разблокирутся.

Нормальное возвращаемое значение — 0; значение -1 возвращается в случае ошибки.

Для получения или изменения текущего значения файловой позиции по дескриптору файла используют функцию lseek (системный вызов 19):

off_t lseek (int filedes, off_t offset, int whence)

Функция lseek используется, чтобы изменить файловую позицию файла с описателем filedes. Аргумент offset — новое смещение файловой позиции относительно whence. Аргумент whence может быть одной из символических констант:

lp12cm

SEEK_SET=0 & Определяет, что whence это число символов от начала файла.
SEEK_CUR=1 & Определяет, что whence это число символов от текущей файловой позиции. Оно может быть положительно или отрицательно.
SEEK_END=2 & Определяет, что whence — число символов с конца файла. Отрицательное число определяет позицию внутри текущего тела файла; положительное число определяет позицию после текущего конца. Если вы устанавливаете позицию после текущего конца, и фактически записываете данные, вы расширяете файл нулями до этой позиции.

Возвращаемое значение lseek — обычно возникающая в результате файловая позиция, измеряемая в байтах от начала файла. Вы можете использовать это средство вместе с SEEK_CUR для чтения текущей файловой позиции.

Вы можете устанавливать файловую позицию после текущего конца файла. Результатом будет соответствующее увеличение размера файла. Сама функция lseek не изменяет файл, но последующий вывод в новую позицию расширит файл.

Если файловая позиция не может быть изменена, или операция выполняется некоторым недопустимым способом, lseek возвращает значение -1.

Можно использовать lseek (desc, 0, SEEK_CUR) для получения текущего значения файловой позиции из описателя, а также lseek (desc, 0, SEEK_END) для определения размера файла.

Задание для выполнения

Написать программу со следующим алгоритмом:

  • вывести на экран приглашение, и ввести с клавиатуры символьную подстроку для поиска;
  • вывести на экран еще одно приглашение, и ввести с клавиатуры символьную строку с именем файла;
  • открыть файл, прочитать его в буфер и найти в содержимом подстроку, используя строковые инструкции;
  • вывести результат поиска в виде сообщения «Найдено» или «Не найдено»;
  • завершить программу.