Для поиска определенного символа или слова в строке используют примитив 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)
для определения размера файла.
Написать программу со следующим алгоритмом:
- вывести на экран приглашение, и ввести с клавиатуры символьную подстроку для поиска;
- вывести на экран еще одно приглашение, и ввести с клавиатуры символьную строку с именем файла;
- открыть файл, прочитать его в буфер и найти в содержимом подстроку, используя строковые инструкции;
- вывести результат поиска в виде сообщения «Найдено» или «Не найдено»;
- завершить программу.