9.1. Строковые операции

Для обработки строковых данных имеются пять команд обработки строк:

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.