Команда scas
scas адрес_приемника
Команда имеет один операнд, обозначающий местонахождение цепочки в дополнительном сегменте (адрес цепочки должен быть заранее сформирован в es:edi/di).
Транслятор анализирует тип идентификатора адрес_приемника, который обозначает цепочку в сегменте данных, и формирует одну из трех машинных команд scasb, scasw или scasd.
Условие поиска для каждой из этих трех команд находится в строго определенном месте. Так, если цепочка описана с помощью директивы db, то искомый элемент должен быть байтом и находиться в al, а сканирование цепочки осуществляется командой scasb; если цепочка описана с помощью директивы dw, то это — слово в ax, и поиск ведется командой scasw; если цепочка описана с помощью директивы dd, то это — двойное слово в eax, и поиск ведется командой scasd. Принцип поиска тот же, что и в команде сравнения cmps, то есть последовательное выполнение вычитания
(содержимое_регистра_аккумулятора - содержимое_очередного_элемента_цепочки).
В зависимости от результатов вычитания производится установка флагов, при этом сами операнды не изменяются.
Так же, как и в случае команды cmps, с командой scas удобно использовать префиксы repe/repz или repne/repnz:
repe или repz — если нужно организовать поиск до тех пор, пока не будет выполнено одно из двух условий:
достигнут конец цепочки (содержимое ecx/cx равно 0);
в цепочке встретился элемент, отличный от элемента в регистре al/ax/eax;
repne или repnz — если нужно организовать поиск до тех пор, пока не будет выполнено одно из двух условий:
достигнут конец цепочки (содержимое ecx/cx равно 0);
в цепочке встретился элемент, совпадающий с элементом в регистре al/ax/eax.
Таким образом, команда scas с префиксом repe/repz позволяет найти элемент цепочки, отличающийся по значению от заданного в аккумуляторе.
Команда scas с префиксом repne/repnz позволяет найти элемент цепочки, совпадающий по значению с элементом в аккумуляторе.
В качестве примера рассмотрим листинг 3, который производит поиск символа в строке.
В программе используется команда-примитив scas.
Символ задается явно (строка 20).
Префикс повторения — repne.
Листинг 3. Поиск символа в строке командой scas <1> ;prg_11_3.asm <2> MASM <3> MODEL small <4> STACK 256 <5> .data <6> ;тексты сообщений <7> fnd db 0ah,0dh,'Символ найден! ','$' <8> nochar db 0ah,0dh,'Символ не найден.','$' <9> ;строка для поиска <10> string db 'Поиск символа в этой строке.',0ah,0dh,'$' <11> .code <12> ASSUME ds:@data,es:@data <13> main: <14> mov ax,@data <15> mov ds,ax <16> mov es,ax ;настройка ES на DS <17> mov ah,09h <18> lea dx,string <19> int 21h ;вывод сообщения string <20> mov al,'а' ;символ для поиска — `а`(кириллица) <21> cld ;сброс флага df <22> lea di,string ;загрузка в es:di смещения строки <23> mov cx,29 ;для префикса repne — длина строки <24> ;поиск в строке (пока искомый символ и символ в строке не совпадут) <25> ;выход при первом совпадении <26> repne scas string <27> je found ;если равны — переход на обработку, <28> failed: ;иначе выполняем некоторые действия <29> ;вывод сообщения о том, что символ не найден <30> mov ah,09h <31> lea dx,nochar <32> int 21h ;вывод сообщения nochar <33> jmp exit ;на выход <34> found: ;совпали <35> mov ah,09h <36> lea dx,fnd <37> int 21h ;вывод сообщения fnd <38> ;теперь, чтобы узнать место, где совпал элемент в строке, <39> ;необходимо уменьшить значение в регистре di и вставить нужный обработчик <40> ; dec di <41> ... вставьте обработчик <42> exit: ;выход <43> mov ax,4c00h <44> int 21h <45> end main |