Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
А С Е М Б Л Е Р.doc
Скачиваний:
7
Добавлен:
12.08.2019
Размер:
835.58 Кб
Скачать

Директиви 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