Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лаба 3-6.923.DOC
Скачиваний:
6
Добавлен:
21.02.2016
Размер:
175.1 Кб
Скачать

Лабораторна робота № 5

Команди обробки рядків

Мета роботи. Вивчити команди обробки рядків мови асемблер.

1. Порядок виконання роботи

    1. Ознайомитися з основними командами обробки рядків мови асемблер.

    2. Розробити алгоритм і написати програму відповідно до варіанта.

    3. Провести відладку програми.

    4. Виконати програму.

2. Зміст звіту

2.1. Тема, мета, порядок виконання роботи.

2.2. Короткий опис основних команд мови асемблер, які використовувалися в даній лабораторній роботі.

2.3. Алгоритм розв’язання задачі.

2.4. Листинг програми (написаний від руки або надрукований).

2.5. Результат виконання програми.

2.6. Висновок.

3. Індивідуальні завдання

3.1. Створити програму, яка містить у собі команди обробки рядків мови асемблер. Виконати введення рядка з 40 символів. Слова в рядку розділити пробілами. Варіанти завдань наведені в табл. 5.

Таблиця 5

Варіант

Завдання: підрахувати кількість слів

Варіант

Завдання: підрахувати кількість літер

1

більше першого

16

у самому довгому слові

2

менше першого

17

у самому короткому слові

3

більше самого короткого

18

"А" у самому довгому слові

4

праворуч самого короткого

19

"C” у самому довгому слові

5

праворуч самого довгого

20

"N" у самому довгому слові

6

менше самого довгого

21

"Z" у самому довгому слові

7

більше останнього

22

"А" у самому короткому слові

8

менше останнього

23

"C" у самому короткому слові

9

і саме довге вивести

24

"N" у самому короткому слові

10

і саме коротке вивести

25

"Z" у самому короткому слові

11

і загальну кількість літер в них

26

у самому короткому слові

12

і кількість літер “A” в них

27

у самому довгому слові

13

і кількість літер “I” в них

28

у словах менше першого

14

і кількість літер “C” в них

29

у словах більше першого

15

і кількість літер “N” в них

30

"P" у самому довгому слові

4. Короткі теоретичні відомості

4.1. CMPS Порівняння рядків

Команда: CMPS destination_string,source_string .

Логіка: CMP (DS:SI), (ES:DI) ; тільки встановлює ознаки

if DF = 0

SI = SI + n ; n = 1 для байта, 2 для слова

DI = DI + n

else SI = SI - n

DI = DI - n .

Ця команда порівнює два значення, віднімаючи байт або слово, на яке указує ES:DI, із байта або слова, на яке указує DS:SI, і встановлює ознаки відповідно до результатів порівняння. Самі операнди не змінюються. Після порівняння, SI і DI збільшуються на 1 (для байтів) або 2 (для слів), якщо ознака напрямку скинута, або зменшуються на 1 або 2, якщо ознака напрямку встановлена. Тим самим готуються до порівняння наступні елементи обох рядків.

Нехай мають місце наступні визначення:

buffer1 db 100 dup (?)

buffer2 db 100 dup (?) .

Тоді наступний приклад виконує порівняння елементів рядків BUFFER1 і BUFFER2 до першої їхньої розбіжності (mismatch):

cld ; скануючи в прямому напрямку,

mov cx, 100 ; 100 байтів (CX використовується в REPE),

lea si, buffer1 ; починаючи з 1-го елемента BUFFER1

lea di, buffer2 ; і з 1-го елемента BUFFER2,

repe cmps buffer1,buffer2 ; порівнюємо їх.

jne mismatch ; ознака ZF = 0, якщо порівнювані

; рядки не збігаються (mismatch)

match: … ; якщо ми потрапили сюди, виходить, вони

… ; збігаються (match)

mismatch:

dec si ; якщо ми потрапили сюди, значить знайшли

dec di ; розбіжність, і повертаємо покажчики SI і DI зворотно,

; щоб вони вказували на перші незбіжні елементи.

Після виходу з циклу REPE CMPS ознака ZF буде скинута, якщо розбіжність була знайдена, і встановлена у протилежному випадку. Якщо розбіжність була знайдена, то DI і SI будуть указувати на байти, що знаходяться безпосередньо за байтами, що не збіглися; DEC DI і DEC SI зменшують значення в цих регістрах таким чином, щоб вони вказували на самі незбіжні байти.

4.2. LODS Завантаження рядка (із байтів або слів)

Команда: LODS source_str .

Логіка: Accumulator = (DS:SI)

if DF = 0

SI = SI + n ; n = 1 для байта, 2 - для слова

else SI = SI - n .

Команда LODS передає байт або слово, розташоване за адресою DS:SI у AX або AL, а також інкрементує або декрементує SI (у залежності від стану ознаки напрямку DF), щоб покажчик перемістився на наступний елемент.

Наступний приклад ілюструє пересилання восьми байтів із INIT_PORT у порт 250. Не намагайтесь робити цього на вашій машині, якщо ви не знаєте про призначення порту 250.

INIT_PORT:

DB '$CMD0000' ; Рядок, що ми хочемо переслати

. . .

CLD ; Будемо пересуватися в прямому напрямку

LEA SI,INIT_PORT ; Засилаємо в SI стартову адресу рядка

MOV CX,8 ; CX є лічильником для команди LOOP

AGAIN: LODS INIT_PORT ; Ім’я INIT_PORT необхідне асемблеру

OUT 250,AL ; тільки для того, щоб визначити має

LOOP AGAIN ; він справу із байтами чи зі словами

4.3. MOVS Пересилання рядка

Команда: MOVS destination,source .

Логіка: (ES:DI) = (DS:SI)

if DF = 0

SI = SI + n ; n = 1 для байта, 2 - для слова

DI = DI + n

else

SI = SI - n

DI = DI - n .

Ця команда пересилає байт або слово, розташоване за адресою DS:SI, до адреси ES:DI. Після пересилання SI і DI інкрементуються (якщо ознака напрямку скинута) або декрементуються (якщо ознака напрямку встановлена), щоб покажчик перемістився на наступний елемент рядка.

Приклад. Припустимо, що рядок BUFFER1 був десь у програмі описаний таким чином: BUFFER1 DB 100 DUP (?)

Тоді наступний приклад описує пересилання 100 байтів із BUFFER1 у BUFFER2:

CLD ; Рухаємося в прямому напрямку

LEA SI,BUFFER1 ; Адресу вихідного (исходного) рядка засилаємо в SI

LEA DI,BUFFER2 ; Адресу рядка призначення засилаємо в DI

MOV CX,100 ; CX використовуємо в префіксі REP

REP MOVS BUFFER1,BUFFER2 ; Робимо пересилання

4.4. SCAS Перегляд рядка

Команда: SCAS destination_string .

Логіка: CMP Accumulator,(ES:DI) ; тільки встановлює ознаки

if DF = 0

DI = DI + n ; n = 1 для байта, 2 для слова

else

DI = DI - n .

Ця команда порівнює акумулятор (AL або AX) із байтом або словом, на яке указує ES:DI, і встановлює ознаки відповідно до результатів порівняння. Самі операнди не змінюються. Після порівняння, DI збільшується на 1 (для байтів) або 2 (для слів), якщо ознака напрямку скинута, або зменшується на 1 або 2, якщо ознака напрямку встановлена. Тим самим готується до порівняння наступний елемент рядка. Команда SCAS корисна в тих випадках, коли потрібно знайти ячейку із заданим байтом або словом. Якщо ви хочете порівняти два рядки з пам'яті поелементно, то використовуйте команду CMPS.

Приклад. Нехай має місце наступне визначення:

LOST_A DB 100 dup (?) .

Тоді наступний приклад описує пошук символу 'А' у блоці пам'яті довжиною 100 байтів, що починається з LOST_A:

MOV AX,DS

MOV ES,AX ; SCAS використовує ES:DI, тому копіюємо DS у ES

CLD ; сканувати будемо в прямому напрямку

MOV AL,'A' ; шукаємо "загублене" 'A'

MOV CX,100; сканувати будемо 100 байтів (CX використовується в REPNE)

LEA DI,LOST_A ; засилаємо стартову адресу в DI

REPNE SCAS LOST_A ; шукаємо 'A'

JE FOUND ; ознака ZF дорівнює 1, якщо ми знайшли 'A'

NOTFOUND : . ; якщо ми потрапили сюди, то 'A' не виявлено

FOUND: DEC DI ; повертаємо покажчик DI на перше виявлене входження 'A'

Після виходу з циклу REPNE SCAS, ZF=1, якщо входження 'A' було виявлено, і ZF=0, інакше. У першому випадку DI указує на байт, що знаходиться за байтом, де знаходиться 'A', тому ми робимо корекцію покажчика DI за допомогою DEC DI.

4.5. STOS Запис у рядок

Команда: STOS destination_string.

Логіка: (ES:DI) = Accumulator

if DF = 0

DI = DI + n ; n = 1 для байта, 2 - для слова

else DI = DI - n .

Команда STOS копіює байт або слово, розташоване в AL або AX, у місце пам'яті, на яке указує (ES:DI), а також інкрементує або декрементує DI (у залежності від стану ознаки напрямку DF), щоб підготуватися до копіювання акумулятора в наступну ячейку (байт або слово) пам'яті.

Приклад: Якщо команду запису в рядок використовувати в сполученні з префіксом REP, то така команда буде корисна для ініціалізації блоку пам'яті; наступний приклад ілюструє ініціалізацію стобайтового блоку пам'яті, розташованого за адресою BUFFER, у 0:

MOV AL,0 ; значення,що привласнюємо при ініціалізації

LEA DI,BUFFER ; завантажуємо стартову адресу блоку пам'яті

MOV CX,100 ; розмір блоку пам'яті

CLD ; будемо рухатися в прямому напрямку

REP STOS BUFFER ; порівняйте цей рядок із ПРИКЛАДом для STOSB

4.6. REP Повтор

Команда: REP КОР (команда обробки рядків) .

Логіка: while CX < > 0 ; для КОР MOVS, LODS або STOS

виконати КОР

CX = CX - 1

while CX < > 0 ; для КОР CMPS або SCAS

CX = CX - 1

if ZF = 0 то закінчуємо цикл .

REP - це префікс, що може бути вжитий перед будь-якою КОР (CMPS, LODS, MOVS, SCAS і STOS). Префікс REP змушує виконуватися наступну за ним КОР у повторному режимі доти, доки CX не стане рівним 0; CX зменшується на 1 після кожного виконання КОР. Для КОР CMPS і SCAS циклічний повтор переривається також, якщо ознака нульового результату ZF виявляється скинутою після чергового виконання КОР. КОР, яка повторюється і була перервана між повторами, буде коректно відновлена після повернення з переривання. Однак, якщо перед КОР знаходяться також інші префікси (наприклад, LOCK) у доповнення до REP, то всі префікси, крім того, що безпосередньо знаходиться поперед команди, будуть втрачені. Тому, якщо вам потрібно використовувати команду з декількома префіксами одночасно, то вам належить заборонити переривання на час виконання команди (і знову дозволити їх після її виконання). Зверніть вашу увагу на те, що навіть такий запобіжний захід не охороняє від немаскованих переривань і обробка довгих рядків може істотно затримувати обробку переривань.

Наступний приклад ілюструє пересилання 100 байтів із BUFFER1 у BUFFER2:

CLD ; рухатися будемо в прямому напрямку

LEA SI, BUFFER1 ; засилаємо в SI і DI стартові адреси

LEA DI, BUFFER2 ; рядків (вихідної і призначення)

MOV CX, 100 ; префікс REP використовує CX як лічильник

REP MOVSB ; здійснюємо пересилання.

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