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

s

Scas адреса_приймача

casd (SCAning String Double Word) - сканувати ланцюжок подвійних слів.

Команда 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_13_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

5. Завантаження елемента ланцюжка в акумулятор

Ця операція-примітив дозволяє витягти елемент ланцюжка і помістити його в регістр-акумулятор al, ax або eax. Цю операцію зручно використовувати разом з пошуком (скануванням) для того, щоб, знайшовши потрібний елемент, витягнути його (наприклад, для зміни). Можливий розмір витягуваного елемента визначається застосовуваної командою.

Програміст може використовувати чотири команди завантаження елемента ланцюжка в акумулятор, що працюють з елементами різного розміру:

lods адреса_джерела (LOaD String) - завантажити елемент з ланцюжка в регістр-акумулятор al/ax/eax;

lodsb (LOaD String Byte) - завантажити байт з ланцюжка в регістр al;

lodsw (LOaD String Word) - завантажити слово з ланцюжка в регістр ax;

lodsd (LOaD String Double Word) - завантажити подвійне слово з ланцюжка в регістр eax.

Розглянемо роботу цих команд на прикладі lods.

К

lods адреса_джерела

оманда lods

Команда має один операнд, що позначає рядок в основному сегменті даних. Робота команди полягає в тому, щоб витягти елемент з ланцюжка за адресою, що відповідає вмісту пари регістрів ds:esi/si, і помістити його в регістр eax/ax/al. При цьому вміст esi/si піддається інкрементe або декрементe (в залежності від стану прапора df) на значення, що дорівнює розміру елемента. Цю команду зручно використовувати після команди scas, що локалізує місце розташування шуканого елементу в ланцюжку. Префікс повторення в цій команді може і не знадобитися - все залежить від логіки програми.

В якості прикладу розглянемо лістинг 4. Програма порівнює командою cmps два ланцюжки байтів в пам'яті string1 і string2 і поміщає перший байт, що не збігся зі string2 в регістр al. Для завантаження цього байту в регістр-акумулятор al використовується команда lods. Префікса повторення в команді lods немає, тому що він просто не потрібний.

Лістинг 4. Використання lods для завантаження байту в регістр al

<1> ;prg_13_4.asm

<2> MASM

<3> MODEL small

<4> STACK 256

<5> .data

<6> ; рядки для порівняння

<7> string1 db 'Пошук символу в цьому рядку.', 0ah, 0dh, '$'

<8> string2 db 'Пошук символу не в цьому рядку.', 0ah, 0dh, '$'

<9> mes_eq db 'Рядки збігаються.', 0ah, 0dh, '$'

<10> fnd db 'Елемент, що не збігся, в регістрі al', 0ah, 0dh, '$'

<11> .code

<12> ; прив'язка ds і es до сегмента даних

<13> assume ds:@data,es:@data

<14> main:

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

<16> mov ds,ax

<17> mov es,ax ; налаштування es на ds

<18> mov ah,09h

<19> lea dx,string1

<20> int 21h ; виведення string1

<21> lea dx,string2

<22> int 21h ; виведення string2

<23> cld ; скидання прапора df

<24> lea di,string1 ; завантаження в es:di зміщення рядка string1

<25> lea si,string2 ; завантаження в ds:si зміщення рядка string2

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

<27> ; пошук в рядку (поки потрібний символ і символ в рядку не рівні)

<28> ; вихід - при першому, що не збігся

<29> repe cmps string1,string2

<30> jcxz eql ; якщо рівні - перехід на eql

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

<32> eql: ; виводимо повідомлення про збіг рядків

<33> mov ah,09h

<34> lea dx,mes_eq

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

<36> jmp exit ; на вихід

<37> no_eq: ; обробка неспівпадання елементів

<38> mov ah,09h

<39> lea dx,fnd

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

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

<42> ;зменшуємо значення регістра si і тим самим переміщаємося до дійсної позиції елемента в рядку

<43> dec si ; команда lods використовує ds:si-адресацію

<44> ; тепер ds:si вказує на позицію в string2

<45> lods string2 ; завантажимо елемент з рядка в AL

<46 > ;Неважко здогадатися, що в нашому прикладі це символ "н"

<47> exit: ;вихід

<48> mov ax,4c00h

<49> int 21h

<50> end main

6. Перенесення елемента з акумулятора в ланцюжок

Ця операція-примітив дозволяє провести дію, зворотну команді lods, тобто зберегти значення з регістра-акумулятора в елементі ланцюжка. Цю операцію зручно використовувати разом з операцією пошуку (сканування) scans і завантаження lods, з тим, щоб, знайшовши потрібний елемент, витягти його в регістр і записати на його місце нове значення. Команди, що підтримують цю операцію-примітив, можуть працювати з елементами розміром 8, 16 або 32 біт. TASM надає програмісту чотири команди збереження елемента ланцюжка з регістра-акумулятора, що працюють з елементами різного розміру:

stos адреса_приймача (STOre String) - зберегти елемент з регістра-аккум. al/ax/eax в ланцюжку;

stosb (STOre String Byte) - зберегти байт з регістра al в ланцюжку;

stosw (STOre String Word) - зберегти слово з регістра ax в ланцюжку;

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