Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Книга_Вычисл техн и микропроц_2 автора_130709.doc
Скачиваний:
9
Добавлен:
07.05.2019
Размер:
5.26 Mб
Скачать

9.4 Створення програм на мові Асемблер-86

9.4.1 Лінійні програми

Вхідний контроль:

  1. Які ділянки програм називаються лінійними?

  2. Команда з якою адресою буде виконуватись після команди

7000:0100 MOV AX,7000H;?

У сучасних додатках рідко використовується програмне забезпечення, цілком написане мовою Асемблера. Частіше мова Асемблера використовується разом з мовою високого рівня, наприклад, С/С++. Частина програми, написана мовою Асемблера, зазвичай призначена для керування периферійними пристроями, оскільки рішення таких задач на мовах високого рівня є більш складним і менш ефективним. Крім того, програми на мові Асемблер виконуються значно швидше, ніж написані будь-якою мовою високого рівня.

Основним принципом отримання ефективних програм є ефективний розподіл та використання ресурсів процесора. Оптимізація програми реалізується за рахунок мінімізації пересилань, використання вказівників на дані замість самих даних при роботі зі складними структурами, розміщення структури даних в одній локальній області пам'яті, розподіл регістрів для локальної ділянки програми тощо. Так, перш за все розподіляються спеціалізовані регістри, а решта виділяється для зберігання найбільш часто використовуваних даних. Дані, які використовуються одноразово, слід зберігати у пам’яті. Акумулятор виділяється для зберігання оперативних результатів.

Потрібна міра оптимальності програми визначається умовами її експлуатації і залежить від багатьох факторів. Для рідко використовуваних програм високий рівень оптимізації не є обов’язковий. Простіше за все оптимізація програми реалізується на лінійних послідовностях команд. У середині лінійних ділянок робиться присвоювання, виконуються операції над даними, вилучаються зайві операції за рахунок одноразового програмування загальних виразів з подальшим включенням їх у циклічні програми. Більш складною задачею є виконання еквівалентних адекватних перетворювань на лінійних ділянках з метою спрощення аналітичних виразів при збереженні достатньої точності та надійності обчислень.

Приклад 9.4.1 Ввести з портів з адресами 3F8H та 2F8H дані та запам’ятати їх у суміжних комірках пам’яті, починаючи з адреси 0020Н у сегменті даних. Округлити їх до 4-х розрядів, упакувати в один байт і зберегти у пам’яті за адресою 0030Н у сегменті даних.

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

Задача вирішується за виконанням наступного фрагмента програми:

MOV DX,3F8H ; Завантаження у регістр DX адреси порту 3F8H

MOV SI,0020H ; Завантаження в індексний регістр SI адреси комірки

; пам’яті для першого даного

MOV DI,0030H ; Завантаження у індексний регістр DI адреси комірки

; пам’яті для упакованого даного

MOV CL,04H ; Завантаження у CL кількості операції зсувів

XOR СН,СН ; Обнулення регістра СН

IN AL,DX ; Введення в акумулятор першого даного з порту

MOV CH,AL ; Запам’ятовування першого даного у регістрі СН

MOV [SI],AL ; Запам’ятовування першого даного у пам’яті

MOV DX,2F8H ; Завантаження у регістр DX адреси порту 2F8H

IN AL,DX ; Введення в акумулятор другого даного з порту

INC SI ; Нарощування адреси комірки пам’яті для другого

; даного

MOV [SI],AL ; Запам’ятовування другого даного у пам’яті

AND CH,F0H ; Округлення першого даного

AND AL,F0H ; Округлення другого даного

SHR AL,CL ; Переміщення округленого другого даного на місце

; другого півбайта

OR CH,AL ; Упаковування даних в один байт

MOV [DI],CH ; Запам’ятовування упакованих даних

NOP

Припустимо, що перше дане D1 становить 12Н (00010010В), а друге D2 – 34Н (00110100В). Округлення першого даного дасть півбайт, який дорівнює 0001В, а другого – 0011В. Упаковане дане складатиме 00010011В або 13Н.

Програма складена з урахуванням подальшої можливості введення із портів масивів даних, їх упакування та запам’ятовування.

Приклад 9.4.2 Число -28Н записати у регістри DL та у прямому коді двома способами. Наступні фрагменти програми виконують ці записи:

а) MOV DL,-28H б) MOV DH,-28H

NEG DL NOT DН

OR DL,80H ADD DН,81H

Запис будь-якого від’ємного числа здійснюється у регістр у доповнювальному коді, тобто у регістрах DL та DH після виконання перших двох команд буде записане число -28Н у доповнювальному коді, тобто число D8H. Для подання цього даного у прямому коді можна використати команду NEG DL, яка подасть це число без знака, а саме 28Н, та команду OR DL,80H, яка установить 1 у старшому розряді. В результаті отримаємо прямий код числа -28Н, який дорівнює А8Н (фрагмент а)). У фрагменті б) число D8H, записане у регістр у доповнювальному коді, інвертується і до нього додається число 81Н. Ця операція установлює 1 у старшому розряді результату і додає 1 до молодшого розряду; у регістрі DL буде записане також число А8Н.

Приклад 9.4.3 Охарактеризувати ознаками ZF, SF та PF дане, яке зберігається у регістрі AL. Команда

OR AL,AL

не змінює дане, яке зберігається в AL, і виставляє зазначені ознаки. У припущенні, що дане є число 56Н, ознаки дорівнюватимуть:

ZF=0;

SF=0;

PF=1.

Приклад 9.4.4 Знайти вміст акумулятора та ознак CF, SF, AF після виконання фрагментів програм:

а) MOV AL,EH б) MOV AL,2AH в) MOV AL,2AH

SUВ AL,2AH SUB AL,4EH SUB AL,E4H

NOP NOP NOP

При виконанні віднімання отримуємо вміст акумулятора:

а) _4EH б) _2AH в) _2AH

2AH 4EH E4H

24H DCH 46H

CF=0 CF=1 CF=1

AF=0 AF=1 AF=0

SF=0 SF=1 SF=0

Ознака CF установлюється в 1, якщо мала місце позика, тобто у фрагментах б) та в). При відніманні із меншого числа більшого ознака CF завжди установлюється в 1, а ознака знаку SF=1 тільки у разі отримання “коректного” результату, тобто за відсутності переповнення розрядної сітки. Для виявлення меншого з двох чисел слід користуватися ознакою CF, якщо аналізується результат виконання команд віднімання або порівняння.

Приклад 9.4.5 При завантаженні комп’ютера тестуються наявні асинхронні адаптери й ініціалізуються перші два з них: СОМ1 та СОМ2, які мають базові адреси 0000:0400Н та 0000:0300Н. Наступний фрагмент програми дозволяє прочитати з регістра керування з адресою 3FBH порту СОМ1 байт стану режиму адаптера:

MOV DX,3FBH ; Завантаження адреси керувального регістра у DX

IN AL,DX ; Введення поточного режиму адаптера

При правильній ініціалізації байт стану дорівнюватиме 000Х0011В = 03Н або 13Н. Це відповідає такому режиму: немає контролю на парність (D3 = 0, D4 = X), один стоповий біт (D2 = 0), кількість бітів дорівнює 8 (D1 = 1, D2 = 1).

Приклад 9.4.6 Два байти D1 та D2 є 3- та 5-м елементами масиву, що починається з ефективної адреси 0010Н. Інвертувати перший байт, вирізати 0, 2, 7 розряди другого; отримані результати зберегти у стеку. Припустимо, що перший байт D1 дорівнює 25Н, а другий D2 – 73Н. Виконаємо вказані операції порозрядно та вкажемо ознаки результату (прапорці) на кожному кроці виконання. Сегменти стека та даних є суміщені.

F1= 11011010 = DAH.

F2 = D2 /\ mask; mask = 01111010 = 7АH.

Задамо довільно 16 елементів масиву байтів, з яких третій дорівнює 25Н, а п’ятий дорівнює 73Н.

7000:0010 12 34 56 25 43 73 43 54 65 76 82 37 15 13 14 61 52.

Вказівник стека задамо таким, який дорівнює 2080Н.

Структурна схема програми наведена на рис. 9.12.

Фрагмент програми, яка вирішує цю задачу, має вид

MOV AX,7000H ; Завантаження

MOV DS,AX ; сегментних

MOV SS,AX ; регістрів

MOV SP,2080H ; Завантаження вказівника стека

MOV BX,0010H ; Завантаження базового регістра

MOV AL,[BX+03] ; Пересилання першого байта до AL

NOT AL ; Інвертування першого байта

MOV AH,[BX+05] ; Пересилання другого байта до АН

AND AH,7AH ; Змінення другого байта

PUSH AX ; Запам’ятовування результатів у стеку

Рисунок 9.12 – Структурна схема програми

Програма виконується так.

Усі команди пересилань та команда NOT не змінюють прапорці; результатом виконання команди NOT є число DAH, що вміщується у регістрі AL, а результатом команди AND є число 72Н, що вміщується в АН; ця команда установлює прапорці OF = 0, CF = 0, SF = 0, AF = 0, ZF = 0, PF = 1.

Приклад 9.4.7 Виконати операцію виключного АБО над двома словами, D1 та D2, що розміщені у пам’яті. Помножити результат на беззнакове число 33Н і розташувати добуток на місці другого слова. Перше знаходиться у масиві, що починається зі зміщення 10Н та адресоване вмістом індексного регістра SI, а друге знаходиться у масиві, що починається зі зміщення 20Н та адресується вмістом індексного регістра DI і зміщенням 2Н. Початкова адреса сегмента даних є 7000Н.

Створимо два масиви, починаючи зі зміщення 10Н та 20Н відповідно. Припустимо, що у регістрі SI міститься число 6Н, а у регістрі DI – число 2Н.

7000:0010 12 34 56 25 40 43 71 43 65 76 82 37 15 13 18 60

7000:0020 14 36 58 27 45 73 48 54 65 76 82 39 17 15 14 61

Тоді перше слово D1 становить 4371Н, а друге D2 дорівнює 7345Н. Перший проміжний результат F1 становить:

F1=D1D2=3034Н.

Ознаки результату становлять OF = 0, CF = 0, SF = 0, AF = 0, ZF = 0, PF = 0.

Другий результат F2 становить:

F2 = F1  33H = 3034H  33H = 99А5СН.

Ознаки результату дорівнюють: OF = 1, CF = 1, SF = 1, AF = 1, ZF = 0.

Програма має вигляд:

MOV AX,7000H ; Організація

MOV DS,AX ; сегмента даних

MOV BX,0010H ; Завантаження до ВХ початкової адреси першого

; масиву

MOV DI,2H ; Завантаження

MOV SI,6H ; індексних регістрів

XOR DX,DX ; Обнулення DX

MOV AX,[BX+SI] ; Завантаження першого слова до АХ

MOV BX,0020H ; Завантаження до ВХ початкової адреси другого

; масиву

XOR AX,[BX+DI+2] ; Складання за модулем 2 з другим словом

MOV CХ,33H ; Завантаження множника до CL

MUL CХ ; Множення на константу 33Н

MOV [BX+DI+2],AX ; Пересилання молодшого слова добутку на місце

; другого слова

MOV [BX+DI+4],DX ; Пересилання старшого слова добутку до другого

; масиву

Після виконання програми в регістр АХ буде записане число 9А5СН, а в регістр DX – число 0009Н.

Контрольні питання:

  1. Як подаються числа беззнакові та зі знаком у МП сім’ї Intel?

  2. Подані в яких системах числення дані можуть оброблюватись у МП сім’ї Intel?

  3. Четвертий елемент першого масиву дорівнює 32Н. Поділити його на п’ятий елемент другого масиву, що дорівнює 4Н, усіма відомими вам способами.

  4. Інвертувати слово, що становить п’ятий елемент першого масиву; поділити результат на третій елемент другого масиву. Частку разом з регістром прапорців запам’ятати у стеку.

  5. Знайти логічний добуток четвертого байта першого масиву та третього байта другого масиву. Результат помножити на 44Н, добуток запам’ятати за ефективною адресою, що визначається вмістом регістра DI.

  6. Заповнити масив з чотирьох слів, починаючи з адреси DS:50, використовуючи команду STOSW.

  7. Порівняти нульовий елемент першого масиву з другим елементом другого масиву. Запам’ятати у стеку вміст регістра прапорців та суму вказаних елементів.

Контрольні питання підвищеної складності:

    1. Завантажити одночасно регістр сегмента даних та акумулятор двобайтовими елементами першого масиву, починаючи з другого елемента за допомогою прямого адресування.

    2. Сумістити сегмент даних та додатковий сегмент даних.