Для обработки строковых данных имеются пять команд обработки строк:
movs — переписать один байт или одно слово из одной области памяти в другую;
lods — загрузить из памяти один байт или одно слово в регистр аккумулятор;
stos — записать содержимое аккумулятора в память;
cmps — сравнить содержимое двух байт или двух слов памяти;
scas — сравнить содержимое аккумулятора с одним словом или с одним байтом памяти.
Префикс REP позволяет этим командам обрабатывать строки любой длины.
Каждая из этих команд не имеет операндов. Данные в них задаются неявно. В этих командах участвуют:
· регистры ds, es, si и di;
· флаг DF.
Обозначим через [ds:si] содержимое байта (или слова), адрес которого задается сегментным регистром ds и индексным регистром si. Аналогично [es:di] обозначает содержимое байта, адрес которого определяется es и di.
Команда movsb действует следующим образом:
байт [ds:si] переписывается в [es:di];
1)
2) если флаг DF равен 0, то si и di увеличиваются на 1, в противном случае оба регистра si и di уменьшаются на единицу.
Команда movsw отличается от movsb тем, что во втором шаге регистры si и di либо оба увеличиваются на 2, либо оба уменьшаются на 2.
Команда lodsb:
1) [ds:si] переписывается в AL;
2) если флаг DF равен 0, то si увеличивается на 1, а если DF=1, то si уменьшается на 1.
Команда lodsw отличается тем, что на первом шаге переписывается в AX содержимое слова [ds:si], а на втором шаге si увеличивается или уменьшается на 2.
Команда stosb:
1) AL переписывается в [es:di];
2) если флаг DF равен 0, то di увеличивается на 1, иначе (в случае DF=1) di уменьшается на 1.
Команда stosw отличается тем, что на первом шаге в [es:di] переписывается AX, а на втором di увеличивается или уменьшается на 2.
Команда cmpsb:
1) сравнивает байты [ds:si] с [es:di] и устанавливает флаги AF, CF, OF, PF, SF и ZF как команда вычитания [ds:si] – [es:di];
2) если DF = 0, то si и di увеличиваются на 1, иначе si и di уменьшаются на 1.
Команда cmpsw отличается тем, что сравниваются слова и на втором шаге si и di увеличиваются или уменьшаются на 2.
Команда scasb:
1) сравнивает AL с [es:di], действует на флаги AF, CF, OF, PF, SF, ZF;
2) если DF =0, то di увеличивается на 1, иначе di уменьшается на 1.
Команда scasw сравнивает AX со словом [es:di] и увеличивает или уменьшает di на 2.
Префикс повторения. Если поставить перед строковой операцией префикс REP, то строковая операция будет повторяться, пока CX не равен 0. Регистр CX уменьшается на 1 после выполнения операции. Например, выполнение команд
lea si,text1
lea di,text2
cld
mov cx,30
rep movsb
приводит к копированию тридцати байт строки text1 в строку text2. Предполагается, что text1 находится в сегменте, на который показывает ds, а text2 – es.
Пример 1. Рассмотрим применение строковой операции stosb для изображения на экране российского флага. В следующей программе в es записывается адрес видеоадаптера, а в регистр di – начальное смещение 0. Затем с помощью команд
mov cx,19200
mov al,15
rep stosb
в видеопамять по адресам A0000h, A0001h,…,A0000h+19199 записываются байты, значения которых равны 15. Эти байты соответствуют 60 строкам экрана, окрашенным в белый цвет. Затем, команды
mov cx,19200
mov al,1
rep stosb
окрашивают аналогичным образом следующие 60 строк в синий цвет, а команды
mov cx,19200
mov al,4
rep stosb
– в красный.
< 1 > title a03.com — Российский флаг
< 2 > codesg segment
< 3 > assume cs:codesg, ds:codesg, ss:codesg
< 4 > org 100h
< 5 > main proc near
< 6 > mov ah,0fh
< 7 > int 10h
< 8 > push ax
< 9 > mov ax,0013h
< 10 > int 10h
< 11 > mov ax,0A000h
< 12 > mov es,ax
< 13 > mov di,0
< 14 > mov cx,19200
< 15 > mov al,15 ;белый
< 16 > rep stosb
< 17 > mov cx,19200
< 18 > mov al,1 ;голубой
< 19 > rep stosb
< 20 > mov cx,19200
< 21 > mov al,4 ;красный
< 22 > rep stosb
< 23 > mov ax,0
< 24 > int 16h
< 25 > pop ax
< 26 > mov ah,0
< 27 > int 10h
< 28 > ret
< 29 > main endp
< 30 > codesg ends
< 31 > end main
Префикс повторения имеет следующие модификации:
REPZ или REPE – повторять операции, пока флаг ZF равен 0; операция закончится, если CX=0 или ZF=1; после каждого выполнения операции CX уменьшается на единицу.
PERNZ или REPNE – повторять операцию, пока флаг ZF равен 1; операция закончится, если CX=0 или ZF=0; после каждого выполнения операции регистр CX будет уменьшаться на 1.
Пример 2. Пусть в сегменте данных определена строка символов
text db 10 dup(‘ ‘);
которая в процессе работы программы изменяется. Напишем подпрограмму поиска символа ‘a’ в этой строке, предполагая, что при ее вызове регистр es установлен на сегмент данных:
finda proc
cld
mov cx,10
lea di,text
mov ah,0 ;символ ‘a’ не найден
mov al,’a’
repne scasb
jne a10
mov ah,1 ;признак того, что ‘a’ найден
a10:
ret
finda endp
Если символ ‘a’ найден в строке, то подпрограмма возвращает ah = 1, а es:di будет адресом позиции, содержащей символ ‘a’. В противном случае подпрограмма возвращает ah = 0.