Снови програмування на мові асемблера архітектури x86.
абораторна робота №1
Мета роботи: Знайомство зі структурою мікропроцесорів Intel. Вивчення особливостей програмування на мові асемблера.
1. Теоретичні відомості
1.1. Регістри процесора 8086
Процесор містить 14 швидкодіючих 16-розрядних чарунок пам’яті, які називаються регістрами. Вони діляться на дві групи регістрів, та два окремих регістри: група регістрів загального призначення – 8 регістрів, група сегментних регістрів – 4 регістри, регістр прапорів та регістр вказівника інструкції, табл.1.
Регістри загального призначення розділяють на регістри даних (АХ, ВХ, СХ, DХ) та регістри вказівників (SI, DI, BP, SP). До регістрів даних можна звертатися як безпосередньо, так і побайтово, так регістр АХ складається з молодшого розряду AL та старшого – AH.
Таблиця 1
Ім’я | English | Призначення |
Регістри загального призначення | ||
AX | Accumulator | Акумулятор (AH, AL), надшвидкий регістр, зв’язаний безпосередньо з АЛП (арифметико-логічним пристроем) мікропроцесора. |
BX | Base | Базовий регістр (BH, BL), використовується при розширеній адресації. |
CX | Counter | Регістр-лічильник (CH, CL), керує числом повторень у циклах. |
DX | Data | Регістр даних (DH, DL), використовується для введення/виведення даних та для обчислень з подвійною точністю, або великими числами при недостатній розрядності акумулятора . |
SI | Source Index | Індексування джерела (SI)/приймача(DI), використовуються при обробці рядкових даних та індексування масивів даних. |
DI | Destination Index | |
BP | Base Pointer | Вказівник бази |
SP | Stack Pointer | Вказівник стека |
Сегментні регістри | ||
CS | Code Segment | Сегмент коду, не можна змінити напряму. |
SS | Stack Segment | Сегмент стеку. |
DS | Data Segment | Сегмент даних. |
ES | Extension Segment | Розширений сегмент даних. |
Регістр прапорів | ||
FLAGS | Інформація про поточний стан процесора. | |
Регістр вказівника команд | ||
IP | Instruction Pointer | Зміщення команд, програмно не доступний. |
Сегментні регістри використовуються для зберігання адрес відповідних сегментів пам’яті. Сегментом називається область пам’яті, яка починається з адреси кратної 16 та містить дані однієї структури. Розрізняють три головні сегменти програми: Сегмент коду (CS) – містить інструкції програми; сегмент даних (DS) – містить дані, задані програмістом; сегмент стеку (SS) – область пам’яті, доступ до якої організований за принципом LIFO (останній зайшов, перший вийшов). Також існує розширений сегмент (ES), який використовується наприклад при роботі з рядковими даними.
1.2. Синтаксис мови асемблера та процес створення програми
Програма на мові асемблера складається з команд та директив. Команди – це інструкції для процесора, директива – керує режимом роботи компілятора.
Формат запису команди асемблеру має вигляд:
мітка: команда операнд(операнди через кому) ;коментарі
Мітка, команда та операнд відокремлюється один від одного символом пробілу або табуляції.
Довжина рядка програми 132 символи, максимальна довжина мітки – 31 символ, коментар починається від символу ; і до кінця рядка. Коментар не відноситься до машинного коду і ігнорується транслятором. Мітка може містити: літери латинської абетки, цифри (не може бути першим символом), спеціальні символи: ? @ _ $ . – тільки на початку мітки.
Мова асемблера може містити змінні, які визначаються за допомогою директив: DB – визначає байт, DW – слово, DD – подвійне слово. Синтаксис:
ім’я DB значення
Вимоги до імені змінної такі ж, як і для мітки. Значення може бути: числовим (14, 4ВH, 1000112b), строковим ('Рядок') та масивом, елементи якого розділяються комою. Змінна являє собою область пам’яті, яка помічена певним ім’ям. Зазвичай всі змінні розміщують в сегменті даних.
Для створення виконуємої програми на мові асемблера необхідне певне програмне забезпечення: компілятор, компоновщик (редактор зв’язків) та налагоджувач (дебагер). Існує велика кількість пакетів подібного програмного забезпечення, найвідоміші з них: TASM, TLINK, TD компанії Borland та MASM, LINK, CV компанії Microsoft.
Програма пишеться в будь-якому текстовому редакторі та зберігається з довільним ім’ям та розширенням ASM. Такий файл називається вихідним модулем. За допомогою компілятора вихідний модуль перетворюється в об’єктний (файл з тим же ім’ям та розширенням OBJ), паралельно може створюватися і файл лістингу, який має розширення LST. А вже об’єктний модуль за допомогою редактора зв’язків перетворюється на виконуєму програму з розширенням COM або EXE.
2. Порядок виконання роботи
1. Створити на диску Е: ПК папку з назвою своєї групи латиницею (наприклад RV91), та скопіювати до неї папку ASM, яка містить три каталоги: BC, VC, ASM_Help
2. В каталозі VC знаходиться Volkov Commander, запускається за допомогою файлу VC.COM. Після запуску доцільно перейти в каталог BC, який містить необхідні для роботи модулі TASM.EXE, TLINK.EXE та TD.EXE.
3. За допомогою комбінації клавіш shift+F4 створити текстовий файл з довільним ім’ям (name) та розширенням asm, що має містити наступний текст програми:
assume cs: code, ds: data
data segment
mes db "Hello, world!$"
fun db 4ch
data ends
code segment
start:
mov ax, data
mov ds, ax
mov ah, 9
mov dx, offset mes
int 21h
mov ah, fun
int 21h
code ends
end start
4. Перетворити текстовий файл у виконуємий модуль. Для цього в командному рядку програми Volkov Commander (переконавшись, що курсор знаходиться в каталозі ВС) викликаємо компілятор, вказавши йому ім’я програми:
tasm name,,
Параметр «,,» після імені файлу вказує компілятору на необхідність створити файл лістингу. У разі відсутності помилок після виконання цієї команди в каталозі ВС буде створено два файли: name.obj та name.lst Перший містить двійковий код програми, а другий містить машинний код, вихідний код та службову інформацію. Також в ньому присутнє описання помилок, якщо такі є в тексті програми.
Наступним кроком є створення виконує мого файлу за допомогою редактора зв’язків. В якості параметру для нього виступає об’єктна програма, для цього в командному рядку необхідно ввести команду:
Tlink name.obj
Розширення файлу .obj можна не вказувати. Результатом роботи редактора зв’язків є створення файлу name.exe,. Переконатися, що створена програма виводить в робочу область командного рядка словосполучення Hello, world!
5. Проаналізувати текст файлу лістингу та розібратися в роботі кожної команди та директиви асемблера.
6. За допомогою команди td name запустити Turbo-debugger, в якому покроково виконати програму з відслідковуванням станів всіх регістрів.
3. Додаткові відомості
3.1. Аналіз файлу лістингу та опис команд
Наведена програма складається з двох сегментів, сегменту даних та сегменту коду. Інформацію про те, який сегмент за що відповідає можна отримати проаналізувавши директиву assume, яка може знаходитися в будь-якій частині програми. Вона вказує компілятору який із сегментів за що відповідає: cs: code – сегмент з ім’ям code є сегментом коду, ds: data – сегмент data – є сегментом даних. Нижче наведено частину файлу лістингу програми:
1 assume cs: code, ds: data
3 0000 data segment
4 0000 48 65 6C 6C 6F 2C 20+ mes db "Hello, world!$"
5 77 6F 72 6C 64 21 24
6 000E 4C fun db 4ch
7 000F data ends
9 0000 code segment
10 0000 start:
11 0000 B8 0000s mov ax, data
12 0003 8E D8 mov ds, ax
13 0005 B4 09 mov ah, 9
14 0007 BA 0000r mov dx, offset mes
15 000A CD 21 int 21h
16 000C 8A 26 000Er mov ah, fun
17 0010 CD 21 int 21h
18 0012 code ends
19 end start
В файлі лістингу можна умовно виокремити 4 стовпчики: в першому знаходиться наскрізна нумерація рядків програми, в другому – зміщення команди чи директиви від початку поточного сегменту, в третьому – шістнадцяткове представлення машинного коду команди чи директиви, а в четвертому власне команда чи директива з коментарями, якщо вони присутні.
Опис команд файлу лістингу:
1 – За допомогою директиви assume визначаються сегменти, див. вище.
3 – відкриття сегменту (директива segment) з іменем data
4 – оголошення змінної mes, яка містить рядок символів, причому під кожен з них виділяється байт (директива db), лапки "" вказують компілятору на те, що це строкова змінна. Фактично в пам’яті виділяється область розміром 14 байт (по кількості символів) в якій розміщений ASCII код символів змінної.
6 – оголошення змінної fun, якій присвоєне значення 4Сh
7 – закриття сегменту з іменем data (директива ends)
9 – відкриття сегменту з іменем segment
10 – встановлено мітку входу start: яка визначає звідки процесору виконувати програму.
11,12 – ініціалізація сегменту даних, тобто в DS заноситься адреса сегменту даних. Команда mov ax, data – заносить в ax ім’я (адресу) сегменту даних data. Команда mov ds, ax переносить вміст регістру ax в регістр ds . Тобто фактично в ds розміщується адреса початку сегменту даних. Однією командою це не можна виконати через особливості сегментних регістрів – в них інформацію можна завантажити виключно з регістрів загального призначення.
13,14,15 – виведення на екран рядка символів:
mov ah, 9 ; – занесення до регістру ah (старший розряд регістра ах) числа 9
mov dx, offset mes ; – інструкція offset визначає що необхідно взяти адресу зміщення початку змінної mes відносно сегменту даних, команда mov заносить його до dx.
int 21h ; – команда int викликає переривання з вказаним номером (в даному випадку 21h). Переривання 21h, це основна операція DOS, яка викликає системну функцію у відповідності з її кодом, завантаженим до регістру ah. Так як в регістрі ah, знаходиться число 9, то виконується виведення рядку символів на екран, адреса початку рядку символів береться з регістру даних (dx), закінченням рядка слугує символ «$».
16 – занесення до регістру ah значення змінної fun, фактично в регістрі ah після виконання команди буде знаходитися 4CH.
17 – Виклик 21 переривання, яке виконую функцію за номером 4CH — завершення програми та повернення до операційної системи.
18 – Директива ends закриває сегмент коду
19 – Директива end завершення програми. В якості операнду вказується мітка входу.
3.2. Опис програми Turbo-debugger
Основні можливості програми Turbo-debugger:
1. Занесення до пам’яті ПК програми та її дизасемблювання.
2. Встановлення точок зупинки
3. Виконання окремих інструкцій програми у покроковому режимі.
4. Аналіз стану всіх регістрів процесора та комірок пам’яті, до яких є прямий доступ.
Зовнішній вигляд вікна TD наведено на рис.1
Інтерфейс містить декілька вікон:
1 – Частина пам’яті з сегментом коду програми
2 – Стани всіх регістрів
3 – Регістр стану процесора
4 – Комірки пам’яті, що відповідають сегменту даних
5 – Комірки пам’яті, що відповідають сегменту стеку
Рис.1 Вікно Turbo-debugger |
4. Зміст звіту
1. Лістинг програми
2. Вікно ТD з завантаженим до нього текстом програми
3. Висновки по роботі
5. Орієнтовні контрольні питання
1. Що міститься в файлах з розширенням asm та obj?
2. Яку інформацію містить файл лістингу?
3. Яку послідовність дій необхідно виконати для створення виконуємої програми?
4. Що таке регістр, які бувають регістри?
5. Які дії виконують команди та директиви Вашої програми?
6. Що таке сегмент?
7. Навіщо потрібен Turbo-debugger?