Если флаг направления DF перед выполнением команды строковой обработки установлен в 0 (выполнена команда CLD), значение в индексном регистре автоматически увеличивается, если в 1 (выполнена STD) – уменьшается. Индексные регистры уменьшаются или увеличиваются на единицу, если команды работают с байтами, или на 2 – если со словами.

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

Команда пересылки строки MOVS (MOVSB, MOVSW)

Команда MOVS пересылает поэлементно строку DS:SI в строку ES:DI и настраивает значения индексных регистров на следующий элемент строки.

Команды, реализующие эту операцию, производят копирование элементов из одной области памяти (цепочки) в другую. Размер элемента определяется применяемой командой. В общем случае набор действий, которые нужно выполнить в программе для того, чтобы выполнить пересылку последовательности элементов из одной области памяти в другую с помощью команды MOVS, можно рассматривать как типовой для выполнения любой цепочечной команды.

1.  Установить значение флага DF в зависимости от того, в каком направлении будут обрабатываться элементы цепочки – в направлении возрастания или убывания адресов.

2.  Загрузить указатели на адреса цепочек в памяти в пары регистров DS:SI и ES:DI.

3.  Загрузить в регистр CX количество элементов, подлежащих обработке.

4.  Выдать команду MOVS с префиксом REP (префикс REP используется только для команд пересылки строк, а для остальных команд используются префиксы REPE, REPZ, REPNE и REPNZ).

НЕ нашли? Не то? Что вы ищете?

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

В системе команд процессора имеется две команды без операндов, которые называются префиксами повторения:

1-ый префикс:

REPE

(повторять, пока равно)

REPZ

(повторять, пока ноль)

REP

(повторять)

2-ой префикс:

REPNE

(повторять, пока не равно)

REPNZ

(повторять, пока не ноль)

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

REPE CMPB

Префикс использует регистр CX как счетчик циклов. На каждом этапе цикла выполняются следующие действия:

1)  проверка CX. Если он равен 0 – выход из цикла и переход к следующей команде;

2)  подтверждение любых возникающих прерываний;

3)  выполнение указанной строковой операции;

4)  уменьшение CX на единицу, флаги при этом не изменяются;

5)  проверка флага ZF, если выполняется строковая операция SCAS или CMPS. Если условие повторения цикла не выполняется – выход из цикла и переход к следующей команде. Выход из цикла, если префиксом является REPE и ZF=0 (последнее сравнение не совпало) или используется префикс REPNE и ZF=1 (последнее сравнение не совпало);

6)  изменение значения индексных регистров в соответствии со значением флага направления и переход на начало цикла.

Команда сравнения строк CMPS (CMPSB, CMPSW)

Команда CMPS сравнивает значение элемента одной строки (DS:SI) со значением элемента второй строки (ES:DI) и настраивает значения регистров на следующие элементы строк в соответствии с флагом направления DF. Сравнение происходит как и по команде сравнения CMP. Результат – сформированные флаги.

В следующем примере с помощью команды CMPS в строках str1 и str2 попарно находятся символы отличные друг от друга. В примере показан оператор Assume, который форматирует привязку сегментных регистров ES и DS к одному сегменту данных. В случае отсутствия данной привязки нельзя назначать указание к одному сегменту данных посредством двух сегментных регистров. Отдельно требуется отметить, что обязательно нужно передавать значение из переменной data и в регистр ES и в регистр DS.

masm

model small

.data

s1 db "‘Строки совпали $"

s2 db "Не совпали символы: $"

str1 db "0123456789" ; Первая строка для сравнения

str2 db "0123456789" ; Вторая строка для сравнения

per db 00h ; Если строки не равны, то per<>0 (первоначально

; per=0)

.code

Assume ds:@data, es:@data ; Привязка DS и ES к сегменту данных

Если данная привязка не будет сделана то команда сравнения строк работать не будет, так как одна из строк должна находиться по адресу DS:SI, а вторая по адресу ES:DI

prog:

mov ah, 00h

mov al, 03h

int 10h

mov ax, @data

mov ds, ax

mov es, ax ; настройка ES на DS

cld ; сброс флага DF – сравнение в направлении

; возрастания адресов

lea si, str1 ; загрузка в si смещения str1

lea di, str2 ; загрузка в di смещения str2

mov cx, 10 ; количество символов в каждой строке (длина

; строк)

met1:

repe cmps str1, str2 ; сравнение пока не конец или пока элементы

; равны

jcxz equal ; переход на метку, если cx=0

mov per, 01h ; изменение per, если есть хотя бы одна пара

; различных символов

mov ah, 09h

lea dx, s2

int 21h

Если строки оказались не равны, произошел выход из операции сравнения cmps. В регистрах si и di содержаться значения смещений относительно начала строк str1 и str2 соответственно. Регистры si и di указывают на следующую пару символов для сравнения. Поэтому, что бы вернуться к паре отличных друг от друга элементов требуется вычесть из этих регистров единицу.

dec si ; уменьшение si на единицу

dec di ; уменьшение di на единицу

mov dl, [di] ; загрузка в dl кода символа по адресу di

mov ah, 02h ; номер функции вывода символа на экран

int 21h ; вывод символа на экран

mov dl, 20h ; загрузка в dl кода символа «пробел»

int 21h ; вывод символа на экран (ah сохранился и не

; требуется его повторная загрузка)

mov dl, [si] ; загрузка в dl кода символа по адресу si

int 21h ; вывод символа на экран

mov dl, 0ah ; загрузка в dl символа перевода строки

int 21h ; переход на новую строку

mov dl, 0dh ; загрузка в dl символа перехода в начало строки

int 21h ; переход в начало строки

inc si ; увеличение si на единицу (возврат к текущему

; состоянию)

inc di ; увеличение di на единицу

jmp met1 ; возврат на процедуру сравнения строк с текущей

; позиции di и si

equal:

mov al, per

cmp per, 00h

jne exit ; если строки не равны, то переменная per будет

; отлична от нуля и произойдет переход на конец

; программы

mov ah, 09h

lea dx, s1

int 21h

exit:

mov ax, 4c00h

int 21h

end prog

Команда сканирования строки SCAS (SCASB, SCASW)

Команда SCAS производит сравнение содержимого регистра (AL или AX) с байтом памяти, абсолютный адрес которого определяется парой ES:DI, после чего регистр DI устанавливается на соседний элемент памяти (байт или слово) в соответствии с флагом DF. Команда SCAS используется обычно для поиска в строке (ES:DI) элемента заданного в регистре AL или AX.

Команды, реализующие эту операцию, производят поиск некоторого значения в области памяти. Логически эта область памяти рассматривается как последовательность (цепочка) элементов фиксированной длины размером 8, 16 или 32 бита. Искомое значение должно быть предварительно помещено в регистр al/ax/eax. Выбор конкретного регистра из этих трех должно быть согласовано с размером элементов цепочки, в которой осуществляется поиск.

В следующем примере с помощью команды SCAS определяется количество вхождений заданного символа symbol в заданную строку str.

masm

model small

.data

simbol db "g"

s1 db "Искомого символа в строке нет","$"

s2 db "В строке искомых символов больше пяти","$"

s3 db "В строке искомых символов меньшне, либо равно пяти","$"

str db "dsgaseggqwdasfswegrwgqf"

per db 00h

.code

Assume ds:@data, es:@data

prog:

mov ah, 00h

mov al, 03h

int 10h

mov ax, @data

mov ds, ax

mov es, ax

cld

lea di, str ; в di записывается адрес строки str

mov al, symbol ; в al помещается код искомого символа

mov cx, 23 ; задается количество символов в строке

met1:

repne scas str ; поиск в строке продолжается пока не будет

; встречен заданный символ, код которого

; находиться в al

jcxz equal ; выход из процедуры поиска если достигнут

; конец строки

add per, 01h ; увеличение счетчика совпадений

jmp met1

equal:

cmp per, 00h ; сравнение количества найденных совпадений с

; нулем

jne yes_simbol ; переход, если найден хотя бы один символ,

; заданный в регистре al

mov ah, 09h

lea dx, s1

int 21h

jmp exit

yes_simbol:

mov al, 5

cmp al, per ; сравнение количества найденных символов с

; числом 5

jnc min_5 ; переход, если количество найденных символов

; больше пяти

mov ah, 09h

lea dx, s2 ; вывод сообщения, если количество совпадений

int 21h ; с заданным символом меньше, либо равно пяти

jmp exit

min_5:

mov ah, 09h

lea dx, s3 ; вывод, если количество совпадений

int 21h ; больше пяти

exit:

mov ax, 4c00h

int 21h

end prog

Команда загрузки строки LODS (LODSB, LODSW)

Команда LODS записывает в регистр AL или AX содержимое ячейки памяти, адрес которой задается регистрами DS:SI. Флаги не меняются.

Эта операция позволяет извлечь элемент цепочки и поместить его в регистр-аккумулятор al, ax или eax. Эту операцию удобно использовать вместе с поиском (сканированием) с тем, чтобы, найдя нужный элемент, извлечь его (например, для изменения). Возможный размер извлекаемого элемента определяется применяемой командой.

Следующий пример посимвольно выводит на экран строку str с помощью команды LODS. В программе настраивается указатель SI на строку str, а в регистре CX задается количество символов в выводимой строке. Содержимое регистра CX указывает, сколько циклов требуется выполнить для вывода всей строки.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10