Сборка - струны
Мы уже использовали строки переменной длины в наших предыдущих примерах. Строки переменной длины могут содержать сколько угодно символов. Обычно мы указываем длину строки одним из двух способов:
- Явное сохранение длины строки
- Использование дозорного персонажа
Мы можем сохранить длину строки явно, используя символ счетчика $ location, который представляет текущее значение счетчика местоположения. В следующем примере -
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
$ указывает на байт после последнего символа строковой переменной msg . Следовательно,$-msgдает длину строки. Мы также можем написать
msg db 'Hello, world!',0xa ;our dear string
len equ 13 ;length of our dear string
В качестве альтернативы вы можете хранить строки с конечным сигнальным символом для разделения строки вместо того, чтобы явно сохранять длину строки. Сторожевой символ должен быть специальным символом, который не появляется в строке.
Например -
message DB 'I am loving it!', 0
Строковые инструкции
Для каждой строковой инструкции может потребоваться операнд-источник, операнд-адресат или и то, и другое. Для 32-битных сегментов строковые инструкции используют регистры ESI и EDI для указания операндов источника и назначения соответственно.
Однако для 16-битных сегментов регистры SI и DI используются для указания источника и назначения соответственно.
Есть пять основных инструкций по обработке строк. Они -
MOVS - Эта инструкция перемещает 1 байт, слово или двойное слово данных из ячейки памяти в другую.
LODS- Эта инструкция загружается из памяти. Если операнд состоит из одного байта, он загружается в регистр AL, если операнд представляет собой одно слово, оно загружается в регистр AX, а двойное слово загружается в регистр EAX.
STOS - Эта инструкция сохраняет данные из регистра (AL, AX или EAX) в памяти.
CMPS- Эта инструкция сравнивает два элемента данных в памяти. Данные могут иметь размер байта, слово или двойное слово.
SCAS - Эта инструкция сравнивает содержимое регистра (AL, AX или EAX) с содержимым элемента в памяти.
Каждая из приведенных выше инструкций имеет версию в байтах, словах и двойных словах, а строковые инструкции можно повторять с помощью префикса повторения.
Эти инструкции используют пару регистров 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.
В следующей таблице представлены различные версии строковых инструкций и предполагаемое пространство операндов.
Базовая инструкция | Операнды в | Байт Операция | Слово Операция | Двойное слово Операция |
---|---|---|---|---|
MOVS | ES: DI, DS: SI | МОВСБ | MOVSW | МОВСД |
LODS | AX, DS: SI | ЛОДСБ | LODSW | LODSD |
STOS | ES: DI, AX | СТОСБ | STOSW | STOSD |
CMPS | DS: SI, ES: DI | CMPSB | CMPSW | CMPSD |
SCAS | ES: DI, AX | SCASB | SCASW | SCASD |
Префиксы повторения
Префикс REP, установленный перед строковой инструкцией, например REP MOVSB, вызывает повторение инструкции на основе счетчика, помещенного в регистр CX. REP выполняет инструкцию, уменьшает CX на 1 и проверяет, равен ли CX нулю. Обработка инструкции повторяется до тех пор, пока CX не станет нулевым.
Флаг направления (DF) определяет направление операции.
- Используйте CLD (Clear Direction Flag, DF = 0), чтобы выполнить операцию слева направо.
- Используйте STD (установить флаг направления, DF = 1), чтобы выполнить операцию справа налево.
Префикс REP также имеет следующие варианты:
РЭП: Это безусловный повтор. Операция повторяется до тех пор, пока CX не станет равным нулю.
REPE или REPZ: условный повтор. Операция повторяется, пока нулевой флаг указывает на равенство / ноль. Он останавливается, когда ZF указывает не равно / нулю или когда CX равен нулю.
REPNE или REPNZ: это также условный повтор. Операция повторяется, пока нулевой флаг указывает не равно / нулю. Он останавливается, когда ZF указывает равный / ноль или когда CX уменьшается до нуля.