Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lekz._13.doc
Скачиваний:
2
Добавлен:
11.08.2019
Размер:
256.51 Кб
Скачать

К

Cmps адреса_приймача,адреса_джерела

оманда cmps:

тут:

адреса_приймача визначається ланцюжком-джерелом в сегменті даних. Адреса ланцюжка має бути заздалегідь завантажена в пару ds:esi/si;

адреса_приймача визначається ланцюжком-приймачем. Ланцюжок повинен знаходитися в додатковому сегменті, і його адреса заздалегідь має бути завантажена в пару es:edi/di.

Алгоритм роботи команди cmps полягає в послідовному виконанні віднімання (елемент ланцюжка-джерела мінус елемент ланцюжка-одержувача) над черговими елементами обох ланцюжків. Принцип виконання віднімання командою cmps аналогічний команді порівняння cmp. Вона, так само, як і cmp, виробляє віднімання елементів, не записуючи при цьому результату, і встановлює прапори zf, sf і of. Після виконання віднімання чергових елементів ланцюжків командою cmps, індексні регістри esi/si і edi/di автоматично змінюються у відповідності зі значенням прапора df на значення, що дорівнює розміру елемента порівнюваних ланцюжків.

Щоб змусити команду cmps виконуватися кілька разів, тобто робити послідовне порівняння елементів ланцюжків, необхідно перед командою cmps визначити префікс повторення. З командою cmps можна використовувати префікс повторення repe/repz або repne/repnz:

repe або repz - якщо необхідно організувати порівняння до тих пір, поки не буде виконано одну з двох умов:

• досягнуто кінець ланцюжка (вміст ecx/cx дорівнює нулю);

• в ланцюжках зустрілися різні елементи (прапор zf став рівним нулю);

repne або repnz - якщо потрібно проводити порівняння до тих пір, поки:

• не буде досягнутий кінець ланцюжка (зміст ecx/cx дорівнює нулю);

• в ланцюжках зустрілися однакові елементи (прапор zf став рівним одиниці).

Таким чином, вибравши відповідний префікс, зручно використовувати команду cmps для пошуку однакових або тих, що розрізняються, елементів ланцюжків. Вибір префікса визначається причиною, яка призводить до виходу з циклу. Таких причин може бути дві для кожного з префіксів. Для визначення конкретної причини найбільше підходить спосіб, який використовує команду умовного переходу jcxz. Її робота полягає в аналізі вмісту регістра ecx/cx, і якщо воно дорівнює нулю, то управління передається на мітку, вказану в якості операнда jcxz. Оскільки в регістрі ecx/cx міститься лічильник повторень для ланцюжкової команди, котра має будь-який з префіксів повторення, то, аналізуючи ecx/cx, можна визначити причину виходу з зациклення ланцюжкової команди. Якщо значення в ecx/cx не дорівнює нулю, то це означає, що вихід відбувся внаслідок збігу або неспівпадання чергових елементів ланцюжків.

Існує можливість ще більше конкретизувати інформацію про причину, що призвела до закінчення операції порівняння. Зробити це можна за допомогою команд умовної передачі управління (табл. 13.2).

Таблиця 13.2 - Поєднання команд умовної передачі управління з результатами команди cmps

для чисел без знака

для чисел зі знаком

Причина припинення операції порівнянняКоманда умовного переходу, що реалізує перехід з цієї причиниПричина припинення операції порівняння

Команда умовного переходу, що реалізує перехід з цієї причини

операнд_джерело > операнд_приймач

ja

операнд_джерело > операнд_приймач

jg

операнд_джерело=

операнд_приймач

je

операнд_джерело=

операнд_приймач

je

операнд_джерело <> операнд_приймач

jne

операнд_джерело <> операнд_приймач

jne

операнд_джерело < операнд_приймач

jb

операнд_джерело < операнд_приймач

jl

операнд_джерело <= операнд_приймач

jbe

операнд_джерело <= операнд_приймач

jle

операнд_джерело =< операнд_приймач

jae

операнд_джерело =< операнд_приймач

jge

Як визначити місце розташування чергових елементів, що збіглися чи не збіглися, в ланцюжках?

Згадайте, що після кожної ітерації ланцюжкова команда автоматично здійснює інкремент/декремент значення адреси у відповідних індексних регістрах. Тому після виходу з циклу в цих регістрах перебуватимуть адреси елементів, що знаходяться в ланцюжку після (!) елементів, які послужили причиною виходу з циклу.

Для отримання істинної адреси цих елементів необхідно скоригувати вміст індексних регістрів, збільшивши або зменшивши значення в них на довжину елемента ланцюжка. В якості прикладу розглянемо програму з лістингу 2, яка порівнює два рядки, що знаходяться в одному сегменті. Використовується команда cmps. Префікс повторення - repe.

Програма досить прозора, пояснити треба тільки два моменти:

• по-перше, рядки 42 і 43, в яких ми скорегували адреси чергових елементів для отримання адрес елементів, що не співпали. Ви повинні розуміти, що якщо порівнюються ланцюжки з елементами слів або подвійних слів, то коригувати вміст esi/si і edi/di потрібно на 2 і 4 байти відповідно;

• по-друге, рядки 47-49. Суть їх у тому, що для перегляду решти рядків необхідно встановити покажчики на наступні елементи рядків за останніми що не співпали. Після цього можна повторити весь процес перегляду й обробки елементів, що не співпали, в останніх частинах рядків.

Лістинг 2. Порівняння двох рядків командою cmps

<1> ;prg_13_2.asm

<2> MODEL small

<3> STACK 256

<4> .data

<5> match db 0ah,0dh,'Рядки співпадають.','$'

<6> failed db 0ah,0dh,'Рядки не співпадають,'$'

<7> string1 db '0123456789',0ah,0dh,'$' ; досліджувані рядки

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

<9> .code

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

<11> main:

<12> mov ax,@data ;завантаження сегментних регістрів

<13> mov ds,ax

<14> mov es,ax ;налаштування ES на DS

<15> ; виведення на екран початкових рядків string1 і string2

<16> mov ah,09h

<17> lea dx,string1

<18> int 21h

<19> lea dx,string2

<20> int 21h

<21> ; скидання прапора DF - порівняння в напрямку зростання адрес

<22> cld

<23> lea si,string1 ; завантаження в si зміщення string1

<24> lea di,string2 ; завантаження в di зміщення string2

<25> mov cx,10 ; довжина рядка для префікса repe

<26> ; порівняння рядків (поки порівнювані елементи рядків рівні)

<27> ; вихід при виявленні елемента, що не збігся

<28> cycl:

<29> repe cmps string1,string2

<30> jcxz equal ; cx = 0, тобто рядки збігаються

<31> jne not_match ; якщо не рівні - перехід на not_match

<32> equal: ; інакше, якщо співпадають, то

<33> mov ah,09h ; виведення повідомлення

<34> lea dx,match

<35> int 21h

<36> jmp exit ; вихід

<37> not_match: ; не співпали

<38> mov ah,09h

<39> lea dx,failed

<40> int 21h ; виведення повідомлення

<41> ; тепер, щоб обробити у рядку елемент, що не збігся, необхідно зменшити значення регістрів si і di

<42> dec si

<43> dec di

<44> ; зараз в ds:si і es:di адреси елементів, що не збіглись

<45> ; тут вставити код з обробки елемента, що не збігся, після цього продовжити пошук в рядку:

<46> inc si

<47> inc di

<48> jmp cycl

<49> exit: ;вихід

<50> mov ax,4c00h

<51> int 21h

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

4. Операція сканування ланцюжків

Команди, що реалізують цю операцію-примітив, проводять пошук деякого значення в області пам'яті. Логічно ця область пам'яті розглядається як послідовність (ланцюжок) елементів фіксованої довжини розміром 8, 16 або 32 біт. Шукане значення попередньо повинне існувати в регістрі al/ax/eax. Вибір конкретного регістра з цих трьох повинен бути узгоджений з розміром елементів ланцюжка, в якому здійснюється пошук.

Система команд мікропроцесора надає програмісту чотири команди сканування ланцюжка. Вибір конкретної команди визначається розміром елементів:

scas адреса_приймача (SCAning String) - сканувати ланцюжок;

scasb (SCAning String Byte) - сканувати ланцюжок байтів;

scasw (SCAning String Word) - сканувати ланцюжок слів;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]