Ассемблер. Строки

  Светлана Деменева  | 

  Обновл. 9 Мар 2021  | 

 20466

 ǀ   1 

На предыдущих уроках мы уже использовали строки разной длины.

Строки в Ассемблере

Строки с переменной в качестве длины могут содержать столько символов, сколько необходимо. Как правило, длина строки указывается одним из следующих двух способов:

   явное содержание длины строки;

   использование сигнального символа.

Мы можем явно хранить длину строки, используя символ счетчика местоположения $, который предоставляет текущее значение счетчика местоположения строки. Например:

Символ $ указывает на byte после последнего символа строковой переменной msg. Следовательно, $ - msg указывает на длину строки. Мы также можем написать:

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

Строковые инструкции


Каждая строковая инструкция может требовать исходного операнда и операнда назначения. Для 32-битных сегментов строковые инструкции используют регистры ESI и EDI, чтобы указать на операнды источника и назначения, соответственно.

Однако для 16-битных сегментов, чтобы указать на источник и место назначения, используются другие регистры: SI и DI.

Существует 5 основных инструкций для работы со строками в Ассемблере:

   MOVS — эта инструкция перемещает 1 byte, word или doubleword данных из одной ячейки памяти в другую;

   LODS — эта инструкция загружается из памяти. Если операндом является значение типа byte, то оно загружается в регистр AL, если типа word — загружается в регистр AX, если типа doubleword — загружается в регистр EAX;

   STOS — эта инструкция сохраняет данные из регистра (AL, AX или EAX) в память;

   CMPS — эта инструкция сравнивает два элемента данных в памяти. Данные могут быть размера byte, word или doubleword;

   SCAS — эта инструкция сравнивает содержимое регистра (AL, AX или EAX) с содержимым элемента, находящегося в памяти.

Каждая из вышеприведенных инструкций имеет версии byte, word или doubleword, а строковые инструкции могут повторяться с использованием префикса повторения.

Эти инструкции используют пары регистров ES:DI и DS:SI, где регистры DI и SI содержат валидные адреса смещения, которые относятся к байтам, хранящимся в памяти. SI обычно ассоциируется с DS (сегмент данных), а DI всегда ассоциируется с ES (дополнительный сегмент).

Регистры DS:SI (или ESI) и ES:DI (или EDI) указывают на операнды источника и назначения, соответственно. Предполагается, что операндом-источником является DS:SI (или ESI), а операндом назначения — место в памяти, на которое указывает пара ES:DI (или EDI).

Для 16-битных адресов используются регистры SI и DI, а для 32-битных адресов используются регистры ESI и EDI.

В следующей таблице представлены различные версии строковых инструкций и предполагаемое место операндов:

Основная инструкция Операнды в: Операция byte Операция word Операция doubleword
MOVS ES:DI, DS:SI MOVSB MOVSW MOVSD
LODS AX, DS:SI LODSB LODSW LODSD
STOS ES:DI, AX STOSB STOSW STOSD
CMPS DS:SI, ES:DI CMPSB CMPSW CMPSD
SCAS ES:DI, AX SCASB SCASW SCASD

Инструкция MOVS

Инструкция MOVS используется для копирования элемента данных (byte, word или doubleword) из исходной строки в строку назначения. Исходная строка указывается с помощью DS:SI, а строка назначения указывается с помощью ES:DI.

Рассмотрим это на практике:

Результат:

Hello, world!

Инструкция LODS


В криптографии шифр Цезаря является одним из самых простых известных методов шифрования. В этом методе каждый символ в открытом тексте заменяется символом, находящимся на некотором постоянном числе позиций левее или правее него в алфавите.

В этом примере давайте зашифруем данные, просто заменив каждую букву алфавита со сдвигом в две буквы, таким образом A будет заменено на C, B на D и т.д.

Мы используем инструкцию LODS для помещения оригинальной строки password в память:

Результат:

rcuuyqtf

Инструкция STOS

Инструкция STOS копирует элемент данных из регистров AL (для byte — STOSB), AX (для word — STOSW) или EAX (для doubleword — STOSD) в строку назначения, на которую указывает ES:DI в памяти.

В следующем примере мы с помощью инструкций LODS и STOS будем конвертировать строки из верхнего регистра в нижний регистр:

Результат:

hello, world

Инструкция CMPS


Инструкция CMPS сравнивает две строки. Эта инструкция сравнивает два элемента данных одного byte, word или doubleword, на которые указывают регистры DS:SI и ES:DI, и устанавливает соответствующие флаги. Вы также можете использовать инструкции прыжков вместе с этой инструкцией.

В следующем примере мы будем сравнивать две строки, используя инструкцию CMPS:

Результат:

Strings are not equal!

Инструкция SCAS

Инструкция SCAS используется для поиска определенного символа или набора символов в строке. Искомый элемент данных должен находиться в регистрах AL (для SCASB), AX (для SCASW) или EAX (для SCASD). Искомая строка должна находиться в памяти, и на нее должны указывать ES:DI (или EDI).

Рассмотрим использование инструкции SCAS на практике:

Результат:

found!

Префиксы повторения


Префикс REP, если он установлен перед строковой инструкцией (например, REP MOVSB), вызывает повторение инструкции на основе счетчика, размещенного в регистре CX. REP выполняет инструкцию, уменьшает CX на 1 и проверяет, равен ли CX нулю. Он повторяет обработку инструкций, пока CX не станет равным нулю.

Флаг направления (DF) определяет направление операции:

   Используйте CLD (англ. «Clear Direction Flag» = «Сбросить флаг направления», DF = 0), чтобы выполнить операцию слева направо.

   Используйте STD (англ. «Set Direction Flag» = «Установить флаг направления», DF = 1), чтобы выполнить операцию справа налево.

Префикс REP также имеет следующие вариации:

   REP — это безусловное повторение, которое повторяет операцию, пока CX не станет равным нулю.

   REPE или REPZ — это условное повторение, которое повторяет операцию до тех пор, пока нулевой флаг (ZF) указывает на равенство нулю результата (сам ZF установлен в единицу). Повторение останавливается, когда ZF указывает на неравенство результата нулю (ZF сброшен в ноль), или когда CX равен нулю.

   REPNE или REPNZ — это также условное повторение, которое повторяет операцию до тех пор, пока нулевой флаг указывает на неравенство нулю результата. Повторение останавливается, когда ZF указывает на равенство нулю результата, или когда CX уменьшается до нуля.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (13 оценок, среднее: 4,38 из 5)
Загрузка...

Комментариев: 1

  1. ex0dus:

    Такой небольшой вопрос возник, зачем мы используем инструкцию rep movsb дляф перемещения строки из si в di если инструкция stosb и так это делает, перемещая изменённую на +2 строку сразу в di? У меня все работает и без rep movsb

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *