Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции / Лекция 7 / Лекция 7.doc
Скачиваний:
23
Добавлен:
10.06.2015
Размер:
159.23 Кб
Скачать

Пересылка байтов, слов и двойных слов

Пересылка байтов, слов и двойных слов производится командами MOVSB, MOVSW и MOVSD. Единственной отличительной особенностью этих команд от команды movs является то, что последняя может работать с элементами цепочек любого размера — 8,16 или 32 бита. При трансляции команда MOVS преобразуется в одну из трех команд: MOVSB, MOVSW или MOVSD. Ранее было показано, что решение о том, в какую конкретно команду будет произведено преобразование, принимается транслятором, исходя из размеров элементов цепочек, адреса которых указаны в качестве операндов команды MOVS. Что касается адресов цепочек, то для любой из четырех команд они должны формироваться программой явно и заранее в регистрах ESI/SI и EDI/DI.

К примеру, посмотрим, как изменится программа из листинга 12.1 при использовании команды MOVSB:

.data

source db "Пересыпаемая строка$" ;строка-источник

dest db 20 DUP (?) ;строка-приемник

.code

ASSUME ds :@data,es:@data

main:

cld ;сброс флага DF — просмотр строки от начала к концу

lea si,source ;загрузка в ES строки-источника

lea di.dest ;загрузка в DS строки-приемника

mov сх,20 ;для префикса гер - длина строки

rep movsb ;пересылка строки

Как видим, изменилась только строка с командой пересылки. Отличие в том, что программа из листинга 12.1 может работать с цепочками элементов любой из трех размерностей: 8,16 или 32 бита, а последний фрагмент — только с цепочками байтов. Далее, как мы и договорились раньше, чтобы не загромождать описания, мы будем рассматривать группы команд для операций-примитивов только на примере более общей команды, а вы будете понимать, что на самом деле можно использовать любую из трех команд в соответствующем контексте.

Сравнение цепочек

Команды, реализующие операцию-примитив сравнения цепочек, производят сравнение элементов цепочки-источника с элементами цепочки-приемника. Здесь ситуация с набором команд и методами работы с ними аналогична операции-примитиву пересылки цепочек. TASM предоставляет программисту четыре команды сравнения цепочек, работающие с разными размерами элементов цепочки:

CMPS адрес_приемника,адрес_источника — сравнить строки (CoMPare String);

CMPSB — сравнить строку байтов (CoMPare String Byte);

CMPSW — сравнить строку слов (CoMPare String Word);

CMPSD — сравнить строку двойных слов (CoMPare String Double word).

Команда cmps

Синтаксис команды CMPS:

cmps адрес_приемника,адрес_источника

Здесь:

адрес_источника определяет адрес цепочки-источника в сегменте данных, заранее загружаемый в пару регистров DS: ESI/SI;

адрес_приемника определяет адрес цепочки-приемника, которая должна находиться в дополнительном сегменте, заранее загружаемый в пару регистров ES:EDI/DI.

Алгоритм работы команды CMPS заключается в последовательном выполнении вычитания (элемент цепочки-источника минус элемент цепочки-получателя) над очередными элементами обеих цепочек. Принцип выполнения вычитания командой CMPS такой же, как у команды сравнения СМР. Она так же, как и СМР, производит вычитание элементов, не записывая при этом результата, и устанавливает флаги ZF, SF и OF. После вычитания очередных элементов цепочек командой CMPS индексные регистры ESI/SI и EDI/DI автоматически изменяются в соответствии со значением флага DF на значение, равное размеру элемента сравниваемых цепочек. Чтобы заставить команду CMPS выполняться несколько раз, то есть произвести последовательное сравнение элементов цепочек, необходимо перед командой CMPS определить префикс повторения. С командой CMPS можно использовать префиксы повторения REP,REPE/REPZилиREPNE/REPNZ:

REP — сравнивать элементы цепочек, пока ЕСХ/СХ>0;

REPE или REPZ — сравнивать элементы цепочек до выполнения одного из двух условий:

-содержимое ЕСХ/СХ равно нулю;

-в цепочках встретились разные элементы (флаг ZF стал равен нулю);

REPNE или REPNZ — сравнивать элементы цепочек до выполнения одного из двух условий:

- содержимое ЕСХ/СХ равно нулю;

- в цепочках встретились одинаковые элементы (флаг ZF стал равен единице).

Таким образом, выбор подходящего префикса позволяет организовать более гибкий поиск одинаковых или различающихся элементов цепочек командой CMPS.

Критерий для выбора префикса — условие выхода из цикла. Для определения конкретного условия наиболее подходящим является способ, использующий команду условного перехода JCXZ. Ее работа заключается в анализе содержимого регистра ЕСХ/СХ, и если оно равно нулю, то управление передается на метку, указанную в качестве операнда JCXZ. Так как в регистре ЕСХ/СХ содержится счетчик повторений для цепочечной команды, имеющей любой из префиксов повторения, то, анализируя ЕСХ/СХ, можно определить условия выхода из цикла цепочечной команды.

Если значение в ЕСХ/СХ не равно нулю, то это означает, что выход произошел по причине совпадения либо несовпадения очередных элементов цепочек. Существует возможность еще больше конкретизировать информацию об условии завершения операции сравнения. Сделать это можно с помощью команд условной передачи управления (табл. 12.1).

Таблица 12.1. Соответствие команд условной передачи управления условиям завершения

команды CMPS

Условие завершения сравнения

Соответствующая команда условного перехода

операнд_источник > операнд_приемник

JA или JG (операнд со знаком)

операнд_источник = операнд_приемник

JE (в том числе для операнда со знаком)

операнд_источник <>операнд_приемник

JNE или JNZ (в том числе для операнда со знаком)

операнд_источник < операнд_приемник

JB или JL (операнд со знаком)

операнд_источник <= операнд_приемник

JBE или JLE (операнд со знаком)

операнд источник >- операнд приемник

JAE или JGE (операнд со знаком)

Как определить местоположение очередных совпавших или несовпавших элементов в цепочках? Вспомните, что после каждой итерации цепочечная команда автоматически осуществляет инкремент-декремент значения адреса в соответствующих индексных регистрах. Поэтому после выхода из цикла в этих регистрах будут находиться адреса элементов, находящихся в цепочке после (!) элементов, послуживших причиной выхода из цикла. Для получения истинного адреса этих элементов необходимо скорректировать содержимое индексных регистров, увеличив либо уменьшив значение в них на длину элемента цепочки.

В качестве примера рассмотрим программу из листинга 12.2, в которой сравнивается две строки, находящиеся в одном сегменте. Используется команда CMPS. Префикс повторения-REPE.

Листинг 12.2. Сравнение двух строк командой CMPS

<l>;prg_12_2.asm

<2>MODEL small

<3>STACK 256

<4>.data

<5>matchdb0ah,0dh,'Сравнение закончено','$'

<6>faileddb0ah,0dh,'Строки не совпадают','$'

<7>stringldb'0123456789',0ah,0dh,'$';исследуемые строки

<8>string2 db '9123406780','$'

<9>.code

<10>ASSUMEes:@data, es:@data ;привязка DS и ES к сегменту данных

<11>main:

<12> mov ax,@data ;загрузка сегментных регистров

<13> mov ds.ax

<14> mov es.ax ;настройка ES на DS

<15>;вывод на экран исходных строк stringl и string2

<16> mov ah,09h

<17> lea dx,stringl

<18> int 21h

<19> lea dx,string2

<20> int 21h

<21>;сброс флага OF - сравнение в направлении возрастания адресов

<22> eld

<23> lea si,stringl ;загрузка в si смещения stringl

<24> lea di,string2 ;загрузка в di смещения string2

<25> mov ex,10 ;длина строки для префикса гере

<26>;сравнение строк (пока сравниваемые элементы строк равны)

<27>;выход при обнаружении несовпавшего элемента

<28>сус1:

<29> jcxz end_hand ;для последнего элемента

<30>гере cmps stringl,string2

<31> je end_hand ;для последнего элемента

<32>;не совпали

<33> mov ah,09h

<34> lea dx,failed

<35> int. 21h ; вывод сообщения

<36>;теперь, чтобы обработать несовпавший элемент в строке,

;необходимо уменьшить значения регистров si и di

<37> dec si

<38> dec di

<39>;сейчас в ds:si и es:di адреса несовпавших элементов

<40>;здесь вставить код по обработке несовпавшего элемента

<41>;после этого продолжить поиск в строке:

<42> inc si

<43> inc di

<44> jmp cycl

<45>end_hand:

<46> mov ah,09h ;вывод сообщения

<47> lea dx,match

<48> int. 21h

<49>exit: ;выход

<50> mov ax,4c00h

<51> int 21h

<52>end main ;конец программы

В программе есть несколько требующих пояснений моментов. Это, во-первых, строки 37 и 38, в которых мы скорректировали адреса очередных элементов для получения адресов несовпавших элементов. Необходимо понимать, что если сравниваются цепочки с элементами слов или двойных слов, то нужно корректировать содержимое регистров ESI/SI и EDI/DI на 2 и 4 байта соответственно. Во-вторых, это строки 42 и 43. Смысл их в том, что для просмотра оставшейся часта строк необходимо установить указатели на следующие элементы строк за последними несовпавшими элементами. После этого можно повторить весь процесс просмотра и обработки несовпавших элементов в оставшихся частях строк. В-третьих, это строки 28—31, с помощью которых учитываются особенности самих строк. Особое внимание следует уделить обработке последних элементов строк в предположении, что они могут не совпасть. Предлагаю вам проследить за выполнением программы в отладчике наследующих наборах входных данных:

stringl = '0123456789' п string2 = '0123406789';

stringl = '0123456789' и string2 = '9123406780',

Соседние файлы в папке Лекция 7