Если флаг направления 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 |


