
Тема: Моделі пам’яті і спрощені детективи.
Організація програми на мові Асемблер
План:
1. Структура програми
2. Директиви розподілу пам'яті
2.1. Псевдокоманди визначення змінних
2.2. Структури
3. Організація програми
3.1. Сегменти
3.2. Моделі пам'яті й спрощені директиви визначення сегментів
3.3. Порядок завантаження сегментів
3.4. Кінець програми
1. Структура програми
Програма мовою асемблера складається з рядків, що мають наступний вид:
мітка команда/директива операнды ; коментар
Причому всі ці поля необов'язкові. Мітка може бути будь-якою комбінацією букв англійського алфавіту, цифр і символів _, $, @, ?, але цифра не може бути першим символом мітки, а символи $ і ? іноді мають спеціальні значення й звичайно не рекомендуються до використання. Великі й маленькі букви за замовчуванням не різняться, але відмінність можна включити, задавши ту або іншу опцію в командному рядку асемблера. У другім полі, полі команди, може розташовуватися команда процесора, яка транслюється в код, що виконується, або директива, яка не приводить до появи нового коду, а управляє роботою самого асемблера. У поле операндов розташовуються необхідні командою або директивою операнды ( тобто не можна вказати операнды й не вказати команду або директиву). І нарешті, у поле коментарів, початок якого відзначається символом ; (крапка з коми), можна написати всі що завгодно — текст від символу «;» до кінця рядка не аналізується асемблером.
Для полегшення читаності ассемблерных текстів прийняте, що мітка починається на першій позиції в рядку, команда — на 17-й (дві табуляції), операнды — на 25-й (три табуляції) і коментарі — на 41-й або 49-й. Якщо рядок полягає тільки з коментаря, його починають із першої позиції.
Якщо мітка розташовується перед командою процесора, відразу після неї завжди ставиться символ «:» (двокрапка), який указує асемблеру, що треба створити змінну із цим іменем, що містить адрес поточної команди:
some_loop:
lodsw ; cчитать слово з рядка,
cmp ax,7 ; якщо це 7 - вийти із циклу
loopne some_loop
Коли мітка стоїть перед директивою асемблера, вона звичайно виявляється одним з операндов цієї директиви й двокрапка не ставиться. Розглянемо директиви, що працюють прямо з мітками і їх значеннями, — LABEL, EQU і =.
мітка label тип
Директива LABEL визначає мітку й задає її тип. Тип може бути одним з: BYTE (байт), WORD (слово), DWORD (подвійне слово), FWORD (6 байт), QWORD (учетверенное слово), TBYTE (10 байт), NEAR (близька мітка), FAR (далека мітка). Мітка одержує значення, рівне адресі наступної команди або наступних даних, і тип, зазначений явно. Залежно від типу команда
mov мітка,0
запише на згадку байт (слово, подвійне слово і т.д.), заповнений нулями, а команда
call мітка
виконає близький або далекий виклик підпрограми.
За допомогою директиви LABEL зручно організовувати доступ до одних й тих самих даних, як до байтів, так і до слів, визначивши перед даними дві мітки з різними типами.
мітка equ вираження
Директива EQU привласнює мітці значення, яке визначається як результат целочисленного вираження в правій частині. Результатом цього виразу може бути ціле число, адреса або будь-який рядок символів:
truth equ 1
message1 equ 'Try again$'
var2 equ 4[si]
cmp ax,truth ; cmp ax,1
db message1 ; db 'Try again$'
mov ax,var2 ; mov ax, 4[si]
Директива EQU найчастіше використовується з метою введення параметрів, загальних для всієї програми, аналогічно команді #define препроцесора мови С.
мітка = вираження
Директива = еквівалентна EQU, але обумовлена нею мітка може приймати тільки цілі значення. Крім того, мітка, зазначена цієї директивою, може бути перевизначена.
Кожний асемблер пропонує цілий набір спеціальних визначених міток — це може бути поточна дата (@date або ??date), тип процесора (@cpu) або ім'я того або іншого сегмента програми, але єдина визначена мітка, яка підтримується всіма асемблерами, — $. Вона завжди відповідає поточній адресі. Наприклад, команда
jmp $
виконує безумовний перехід на саму себе, так що створюється вічний цикл із однієї команди.
2. Директиви розподілу пам'яті
2.1. Псевдокоманди визначення змінних
Псевдокоманда — це директива асемблера, яка приводить до включення даних або коду в програму, хоча сама вона ніякій команді процесора не відповідає. Псевдокоманди визначення змінних указують асемблеру, що у відповіднім місці програми розташовується змінна, визначають тип змінної (байт, слово, речовинне число і т.д.), задають її початкове значення й ставлять у відповідність змінної мітку, яка буде використовуватися для звертання до цих даних. Псевдокоманди визначення даних записуються в загальному виді в такий спосіб:
ім'я_змінної d* значення
де D* — одна з нижчеподаних псевдокоманд:
DB — визначити байт;
DW — визначити слово (2 байта);
DD — визначити подвійне слово (4 байта);
DF — визначити 6 байт (адреса у форматі 16-бітний селектор: 32-бітний зсув);
DQ — визначити учетверенное слово (8 байт);
DT — визначити 10 байт ( 80-бітні типи даних, використовувані FPU).
Поле значення може містити одне або кілька чисел, рядків символів (узятих в одиночні або подвійні лапки), операторів ? і DUP, розділених комами. Усі встановлені в такий спосіб дані виявляться у вихідному файлі, а ім'я змінної буде відповідати адресі першого із зазначених значень. Наприклад, набір директив
text_string db 'Hello world!'
number dw 7
table db 1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
float_number dd 3.5e7
заповнює даними 33 байта. Перші 12 байт містять Ascii-Коди символів рядка «Hello world!», і змінна text_string указує на першу букву в цьому рядку, так що команда
mov al,text_string
пересилає в регістр AL число 48h (код латинської букви H). Якщо замість точного значення зазначений знак ?, змінна вважається неінициализированною і її значення на момент запуску програми може виявитися кожним. Якщо потрібно заповнити ділянку пам'яті повторюваними даними, використовується спеціальний оператор DUP, що має формат лічильник DUP (значення). Наприклад, от таке визначення:
table_512w dw 512 dup(?)
створює масив з 512 неинициализированних слів, на перше з яких указує змінна table_512w. У якості аргументу в операторові DUP можуть виступати кілька значень, розділених комами, і навіть додаткові вкладені оператори DUP.
2.2. Структури
Директива STRUC дозволяє визначити структуру даних аналогічно структурам у мовах високого рівня. Послідовність директив
ім'я struc
поля
ім'я ends
де поля — будь-який набір псевдокоманд визначення змінних або структур, установлює, але не інициализирует структуру даних. Надалі для її створення в пам'яті використовують ім'я структури як псевдокоманду:
мітка ім'я <значення>
І нарешті, для читання або запису в елемент структури використовується оператор «.» (крапка). Наприклад:
point struc ; Визначення структури
x dw 0 ; Три слова зі значеннями
y dw 0 ; за замовчуванням 0,0,0
z dw 0
color db 3 dup(?) ; і три байти
point ends
cur_point point <1,1,1,255,255,255> ; Ініціалізація
mov ax,cur_point.x ; Звертання до слова "x"
Якщо була визначена вкладена структура, доступ до її елементів здійснюється через ще один оператор «.» (крапка).
color struc ; Визначити структуру color.
red db ?
green db ?
blue db ?
color ends
point struc
x dw 0
y dw 0
z dw 0
clr color <>
point ends
cur_point point <>
mov cur_point.clr.red,al ; Звертання до червоного компонента
; кольору крапки cur_point.