Поле операндів.
Поле операндів залежить від попереднього поля.
Поле коментарів.
Структура програми на мові asm.
При роботі будь-якої програми в будь-який момент часу можна виділяти декілька ділянок пам’яті з якими працює процесор. Використання сегментів є особливістю процесорів х86. Воно переслідує таку мету:ами.
За вання сегментів є спробою заха вити незв’язані ділянки пам’яті в програмі. Допускалось, що для того, щоб визначити адресу деякої комірки пам’яті потрібно знати дві складові цієї адреси: адресу початкового сегменту та адресу зміщення комірки пам’яті від початку сегменту. Адреси початків сегментів знаходяться у відповідних сегментах регістрах CS, DS, SS, ES – змінюючи вміст цих регістрів можна дістати доступ до тих чи інших ділянок пам’яті, тому такий запис легко зламати. Тому в процесорі 386 в захащеному режимі роботи адреси початків сегментів, їх довжини та права доступу зберігаються в спеціальних системних одиницях. В сегментних регістрах зберігають тільки індекс структури всередині таблиці. Це дозволило ізолювати сегменти та обмежило доступ до них з програми. Адже для доступу потрібно знати не тільки вміст сегменту регістру, але й тієї структури на яку він вказує. Така зміна можлива тільки при використанні привілейованих команд, що виконується тільки в певних умовах, можуть виконуватись в ОС, але не можуть використовуватись в програмах користувача. Паралельно з цим збільшення розміру сегментів:амід 64Кб для 86, до 4Гб для 486. Крім того програма буде виконуватись, якщо змінити адресу початку сегменту. Це означає, що в пам’яті він буде перенесений в інше місце. При цьому відносне зміщення в сегменті не можна зміщувати. Це дозволить переносити програму в пам’яті навіть під час її виконання. Використання сегментації пам’яті дозволяє різко збільшити розміри пам’яті, яку можна використати. Так, в захащеному режимі максимально можливий об’єм пам’яті, яку можна адресувати – 64Тб. Це віртуальна пам’ять. Тоді як фізичний об’єм пам’яті складає 4Гб. В деяких випадках використовувати сегментацію недоцільно. Тому в старших моделях можна працювати із сегментами довжиною до 4Гб. Це означає, що вся фізична пам’ять розглядається як один сегмент. Повністю усі переваги сегментації пам’яті проявляється в захащеному режимі роботи. В реальному режимі роботи оперує з 4-ма сегментами:а
1. Сегмент коду;
2. Сегмент даних;
3. Сегмент стеку;
4. Сегмент додаткових даних.
Для процесорів 386 з’явились ще 2 сегменти додаткових даних. Ці сегменти в пам’яті можуть розташиняватись як завгодно по відношенню один до одного. Ніяких обмежень на їх розташування немає. Сегменти можуть починатись з однієї адреси, тобто можуть перекриватись. Вони можуть розташиняватись в пам’яті без перекривання, або між ними можуть бути проміжки.
Для визначення адреси наступної команди після виконання попередньої використовують 2 регістри: CS (регістр сегменту коду, він містить початок адресу цього сегменту), і IP(регістр вказівника команд, якість зміщення команди відносно початку сегменту). В процесі виконання програми вміст ІР автоматично змінюється. Якщо змінити вміст регістрів CS, та ІР, то виклик програми почнеться з іншої адреси. Але явним чином змінити вміст цих регістрів неможливо. Це можна зробити тільки при використані деяких команд. Наприклад при виклику підпрограми. Або виконані програми безумовного переходу. Як уже відмічалось в сегменті коду можна також описувати дані. Але це роблять тільки в обгрунтованих випадках, наприклад в програмі обробки переривань.
Початок програми.
В початковій версії необхідно було відмітити точку входу в програму деякою міткою. Ім’я цієї мітки потім вказувалось в директиві end. Це було ознакою закінчення файлу з програмою. У сучасних асемблерах для визначення точки входу в програму використовується директива startup. Вона записується в сегменті коду, це спрощує запис і, крім цього, автоматично ініціалізує значення сегментних регістрів. В старих версіях це потрібно було робити вручну.
Кінець програми.
Для закінчення програми потрібно було скористяватись стандартною директивою. Вона робить відповідний виклик автоматично. Якщо програму необхідно закінчити спеціальним чином, наприклад встановити резидентну програму, то користяватись цією директивою не можна. В таких випадках потрібно явно викликати відповідну функцію операційної системи.
Змінні в програмі.
В усіх інших сегментах виділяється місце для змінних, що використовуються в програмі. Поділ сегментів на сегменти даних, стеку та додаткових даних зумовлена тим, що змінні, які тут визначені мають різні властивості. Змінні в програмі можна розбити на 2 великі групи:
1. Змінні, які явна використовуються в програмі виходячи з її логіки. Такі змінні як правило мають імена і використовуються вони для збереження даних, які мають наперед визначений зміст. Наприклад, змінна що використовується для збереження коду натиснутої клавіші.
2. Часто в програмі необхідно мати місце для збереження тимчасових даних.
Сегмент даних.
Використовується для збереження змінних, що визначає програміст. Як правило це робиться при допомозі псевдооператорів виділення пам’яті. Для визначення адреси початку сегменту використовується регістр DS. Для визначення другої компоненти адреси (відповідного зміщення всередині сегменту) використовується кілька способів адресації. Зауважимо, що способів визначення адреси змінної набагато більше ніж способів визначення адреси команди. В мові асемблер є засоби для явного розділ. збереження змінних. Ці змінні можуть мати або не мати початкових значень, а також можуть бути змінними константами. Розділяти ці типи змінних не обов’язково. Усіх їх можна зберігати в сегменті даних.
Ініціалізовані змінні.
Змінні, початкові значення яких відоме як правило записуються в сегменті, що починається директивою data. До цих змінних відносяться також ті, початкові значення яких відоме і в процесі роботи вони не повиннVпмінятись.
Неініціалізовані змінні.
Неініціалізовані змінні записуються в сегмент який починається директивою data.
Сегмент стеку використовується для збереження тимчасових даних для яких недоцільно виділяти змінні. Адреса початку цього сегменту розміщується в регістрі SS, а зміщення відносно початку в регістрі SP. Для визначення сегменту стеку використовується директива stack. Цей сегмент відрізняється від сегменту даних і коду. В сегменті даних і коду можна явно адресувати б-я комірку пам’яті. Тут значення регістру при виконанні команд. В кожний момент часу пара цих регістрів SS і SP вказує на так звану вершину стеку. Сюди можна записати або прочитати значення. Стек організований за правилом: перший записаний, останній прочитаний. Тому у програмі команди запису і зчитування зі стеку потрібно використовувати попарно. Стек переважно використовується для тимчасового зберігання адреси повернення з програми або перервань. Ще одне ми.
За вання стеку – при його допомозі можна передавати аргументи підпрограмам і організовувати локальні змінні.
Лекція за 1.10.
Моделі пам’яті
1. Tiny (файл *.com). При цьому регістри CS, DS, SS містять однакові значення. Це найбільш компактна модель пам’яті. Розмір пам’яті не може перевищувати 63Кб. Адресація здійснюється за допомогою зміщення і міток. Оскільки програма на асемблері не є великими, то це не є значним обмеженням. Ця модель широко використовується, особливо в резидентних програмах.
2. Small. Сегмент коду відділений від сегменту стеку і сегменту даних. Сегмент даних і стеку об’єднані в єдине. Тому CS і DS мають однакові значення. Це найбільш поширена модель при розробці програм на асемблері. Всі переходи і виклики підпрограм здійснюються за допомогою короткої адресації.
3. Compact. Використовується 1 сегмент коду і можливе ми.
3.За вання кількох сегментів даних. тому виклики підпрограм і переходи в програмі є короткими, а доступи до даних – далекими. Сегмент даних і стек об’єднані в одну групу.
4. Medium. В значній мірі протилежна до попередніх. Є кілька сегментів коду і один сегмент даних. Тому доступ до підпрограм і переходи в програмі є далекими (потрібна адреса сегменту та зміщення). А доступ до даних здійснюється за допомогою короткої адресації (вказується тільки зміщення).
5. Large. Це найбільш загальний спосіб організації пом’яті. Тут можуть використовуватись декілька сегментів коду і даних. Доступ до змінних, переходи на мітки здійснюються за допомогою адреси сегментів та зміщень.
6. Huge, Flat. Це досить поширені моделі. Така ж організація пам’яті, як і в large. Вона використовується для поєднання асемблера змовами високого рівня. В них можна задати таку модель пам’яті, з’являється можливість роботи з даними що займають більше 64 Кб. В програмі на асемблері таку модель використовувати недоцільно. Модель Flat відповідає моделі Small, різниця в тому, що використовуються 32 розрядні регістри. Таку модель можна організувати використовуючи процесор вище і80386. Переважно її використовують для роботи в захащеному режимі. В цьому випадку доступ до всієї області пам’яті здійснюються за допомогою одного сегменту.
При програмуванні на асемблері краще використовувати перші 2 моделі пам’яті. Можна використовувати інші моделі, але в цих випадках програма ускладнюється, адже доводиться слідкувати за розміщенням кожного сегменту. Для визначення моделі пам’яті використовується директива model, що має такий формат запису: