![](/user_photo/2706_HbeT2.jpg)
- •Регістри загального призначення процесора 8086
- •Р егістри спеціального призначення процесора 8086
- •Набір інструкцій процесора
- •Xchg ах, bx ; Міняємо місцями вміст ах і bx
- •Визначення даних
- •Виклик функцій bios і операційної системи
- •Директиви segment, assume, end і .386
- •Приклад визначення сегменту:
- •X db ? ; байт пам'яті, початкове значення якого не визначено
- •Управління пам'яттю процесора
- •Типи адресації 8086
- •Типи адресації 80386
- •Контроль над програмним потоком
- •Команди переходу після зіставлення чисел з урахуванням знака:
Директиви segment, assume, end і .386
Будь-яка програма складається з набору машинних команд і даних, які під час виконання знаходяться в пам'яті. Іноді для роботи програми необхідне також додаткове місце, наприклад під стек. У принципі, можливо сумісне розміщення команд, даних і стека в одному блоці пам'яті, але тоді з'являється небезпека при записі в стек або область даних пошкодити команди, а також ускладниться відладка програми. Тому, целесообразнее використовуватиме різні області пам'яті (сегменти) для зберігання команд процесора, даних, і для реалізації стека.
Операційна система повинна знати, скільки пам'яті необхідно виділяти під програму, які сегменти потрібно визначити при запуску, і ніж їх потрібно заповнити, а також місцезнаходження команди, починаючи з якою відбувається виконання програми – так званої «точки входу». Вся ця і інша корисна інформація знаходиться у виконуваному файлі програми.
Для того, щоб транслятор асемблера знав, в який сегмент потрібно покласти певні дані або команди, використовується директива SEGMENT:
<имя сегмента> SEGMENT [параметри]
. . .
команди/дані
. . .
<имя сегмента> ENDS
Як параметри можна вказати додаткову інформацію про сегмент. Наприклад, параметр STACK указує операційній системі, що цей сегмент використовуватиметься, як системний стек.
Приклад визначення сегменту:
DATA SEGMENT
X db ? ; байт пам'яті, початкове значення якого не визначено
У DW 100 ; два байти, що містять число 100
DD 10 dup (0) ; 40 обнулених байт
DATA ENDS
Для того, щоб транслятор міг більш розумно працювати з мітками і змінними (наприклад, сам враховував розмір даних), а також знав, які значення потрібно записати в сегментні регістри при запуску програми, необхідно «зв'язати» певні сегменти і сегментні регістри. Це робиться за допомогою директиви ASSUME.
ASSUME <сегментный регистр>:<имя сегмента> [ <сегментный регистр>:<имя сегмента> ...]
Наприклад, якщо програма використовує роздільні сегмент коду і сегмент даних з іменами CODE і DATA:
ASSUME cs:CODE, ds:DATA
Існує ще одна спеціальна директива, без якої програма не буде працездатною – це директива END. Вона має відразу два призначення – позначення кінця програми і визначення точки входу в неї.
END <адрес крапки входа>
Наприклад, якщо при запуску програма повинна перейти на мітку beg:
...
beg: MOV АХ, 10
...
END beg
З директивою .386 все здавалося б просто – вона говорить транслятору, що програма написана для процесора 80386. Але річ у тому, що після вказівки цієї директиви транслятор автоматично настроюється на 32-розрядну адресацію, що не підтримується програмою tlink.exe. Для запобігання цього, необхідно для вказати, що ми використовуємо 16-бітовий зсув усередині сегменту за допомогою параметра USE16 директиви SEGMENT.
DATA SEGMENT USE16
Тепер явно вказано, що сегмент DATA – 16-бітовий.
Компіляція програми
Для того, щоб створити з тексту програми працездатний виконуваний EXE-файл, необхідно виконати дві дії – створити з тексту об'єктний файл (OBJ), а потім з об'єктного – виконуваний.
Для цього, в командному рядку ДОС необхідно виконати дві команди:
tasm prog.asm - для трансляції програми в OBJ-файл
tlink prog.obj - для створення з OBJ-файлу EXE-файлу
Тут prog.asm – ім'я початкового файлу з текстом програми. Також, необхідна наявність в поточному каталозі файлів tasm.exe і tlink.exe.
Завдання на лабораторну роботу
Написати програму для процесора 8086, яка виводить на екран заданий у варіанті символ, виконує над його кодом вказану дію, а потім виводить на екран отриманий символ. Результат операції повинен зберігатися в сегменті даних. Перед виходом в ДОС необхідно викликати функцію читання символу з клавіатури, щоб забезпечити затримку для проглядання результату. Відстежити роботу програми у відладчику.
Приклад виконання роботи
ASSUME CS:CODE, DS:DATA ; зв'язуємо сегментні регістри і сегменти
DATA SEGMENT ; сегмент даних
res db ? ; тут буде результат
DATA ENDS
CODE SEGMENT ; сегмент коду
beg: MOV AH, 2 ; функція 2 – висновок символу
MOV DL, ‘@’ ; власне, символ
INT 21h ; виклик переривання ДОС
ADD DL, 32 ; виконуємо дію (додати 32)
MOV res, DL ; зберігаємо результат
INT 21h ; виводимо результат (в AH залишилася 2-но)
MOV AH, 1 ; функція 1 – прочитування символу
INT 21h ; виклик переривання ДОС
MOV АХ, 4c00h ; вихід з кодом виходу «0»
INT 21h ; виклик переривання ДОС
CODE ENDS
END beg ; точка входу - beg