Структура команди мовою асемблера містить. Загальна характеристика системи команд мови Assembler для IBM-PC (базовий набір команд, основні способи адресації операндів). Структура програми мовою Assembler. Програмні сегменти. Директива assume

Тема 1.4 Асемблерна мнемоніка. Структура та формати команд. Види адресації. Система команд мікропроцесора

План:

1 Мова асемблера. Основні поняття

2 Символи мови асемблера

3 Типи операторів асемблера

4 Директиви асемблера

5 Система команд процесора

1 Ягук асемблера. Основні поняття

Мова асемблера- це символічна вистава машинної мови. Всі процеси в машині на найнижчому апаратному рівні приводяться в дію тільки командами (інструкціями) машинної мови. Звідси зрозуміло, що, незважаючи на загальну назву, мова асемблера для кожного типу комп'ютера своя.

Програма на асемблері є сукупністю блоків пам'яті, званих сегменти пам'яті.Програма може складатися з одного або кількох блоків-сегментів. Кожен сегмент містить сукупність речень мови, кожна з яких займає окремий рядок коду програми.

Пропозиції асемблера бувають чотирьох типів:

1) команди або інструкції, являють собою символічні аналоги машинних команд. У процесі трансляції інструкції асемблера перетворюються на відповідні команди системи команд мікропроцесора;

2) макрокоманди -оформлювані певним чином пропозиції тексту програми, які замінюються під час трансляції іншими пропозиціями;

3) директиви,є вказівкою транслятора асемблера виконання деяких дій. У директив немає аналогів у машинному поданні;

4) рядки коментарів , що містять будь-які символи, у тому числі й літери російської абетки. Коментарі ігноруються транслятором.

­ Структура програми на асемблері. Синтаксис асемблера.

Пропозиції, що становлять програму, можуть бути синтаксичною конструкцією, що відповідає команді, макрокоманді, директиві або коментарю. Для того, щоб транслятор асемблера міг розпізнати їх, вони повинні формуватися за певними синтаксичними правилами. Для цього найкраще використовувати формальний опис синтаксису мови на кшталт правил граматики. Найбільш поширені способи подібного опису мови програмування - синтаксичні діаграмиі Розширені форми Бекуса-Наура.Для практичного використаннязручніші синтаксичні діаграми.Наприклад, синтаксис речень асемблера можна описати за допомогою синтаксичних діаграм, показаних на наступних малюнках 10, 11, 12.

Малюнок 10 - Формат пропозиції асемблера


­ Малюнок 11 - Формат директив

­ Малюнок 12 - Формат команд та макрокоманд

На цих малюнках:

­ ім'я мітки- ідентифікатор, значенням якого є адреса першого байта пропозиції вихідного тексту програми, яке він позначає;

­ ім'я -ідентифікатор, який відрізняє цю директиву від інших однойменних директив. Через війну обробки асемблером певної директиви цього імені може бути присвоєно певні характеристики;

­ код операції (КОП) та директива - це мнемонічні позначення відповідної машинної команди, макрокоманди чи директиви транслятора;

­ операнди -частини команди, макрокоманди або директиви асемблера, що позначають об'єкти, над якими виконуються дії. Операнди асемблера описуються виразами з числовими та текстовими константами, мітками та ідентифікаторами змінних з використанням знаків операцій та деяких зарезервованих слів.

Синтаксичні діаграми допомагають знайти і потім пройти шлях від входу діаграми (ліворуч) до її виходу (праворуч). Якщо такий шлях існує, то пропозиція чи конструкція синтаксично правильні. Якщо такого шляху немає, то цю конструкцію компілятор не прийме.

­ 2 Символи мови асемблера

Допустимими символами при написанні тексту програм є:

1) Усе Латинські букви: A-Z,a-z. При цьому великі та малі літери вважаються еквівалентними;

2) цифри від 0 до 9 ;

3) знаки ? , @ , $ , _ , & ;

4) роздільники , . () < > { } + / * % ! " " ? = # ^ .

Пропозиції асемблера формуються з лексем, що являють собою синтаксично нероздільну послідовність допустимих символів мови, що мають сенс для транслятора.

Лексемамиє:

1) ідентифікатори - послідовності допустимих символів, що використовуються для позначення таких об'єктів програми, як коди операцій, імена змінних та назви міток. Правило запису ідентифікаторів полягає в наступному: ідентифікатор може складатися з одного або кількох символів;

2) ланцюжки символів - послідовності символів, укладені в одинарні або подвійні лапки;

3) цілі числав одній з наступних систем числення : двійковій, десятковій, шістнадцятковій. Ототожнення чисел під час запису в програмах на асемблері проводиться у разі певним правилам:

4) десяткові числа не вимагають для свого ототожнення вказівки будь-яких додаткових символів, наприклад 25 або 139. Для ототожнення у вихідному тексті програми двійкових чиселнеобхідно після запису нулів та одиниць, що входять до їх складу, поставити латинське “ b”, наприклад 10010101 b.

5) шістнадцяткові числа мають більше умовностей при своєму записі:

По-перше, вони складаються з цифр 0...9 , малих і великих літер латинського алфавіту a,b, c,d,e,fабо A,B,C,D,E,F.

По-друге, у транслятора можуть виникнути труднощі з розпізнаванням шістнадцяткових чисел через те, що вони можуть складатися з одних цифр 0...9 (наприклад, 190845), так і починатися з літери латинського алфавіту (наприклад, ef15). Для того, щоб "пояснити" транслятору, що дана лексема не є десятковим числом або ідентифікатором, програміст повинен спеціальним чином виділяти шістнадцяткове число. Для цього на кінці послідовності шістнадцяткових цифр, що становлять шістнадцяткове число, записують латинську букву “ h”. Це обов'язкова умова. Якщо шістнадцяткове число починається з літери, перед ним записується провідний нуль: 0 ef15 h.

Практично кожна пропозиція містить опис об'єкта, над яким або за допомогою якого виконується певна дія. Ці об'єкти називаються операндами. Їх можна визначити так: операнди- це об'єкти (деякі значення, регістри чи осередки пам'яті), куди діють інструкції чи директиви, або це об'єкти, які визначають чи уточнюють дію інструкцій чи директив.

Можливо, провести наступну класифікацію операндів:

­ постійні чи безпосередні операнди;

­ адресні операнди;

­ операнди, що переміщаються;

лічильник адреси;

­ регістровий операнд;

­ базовий та індексний операнди;

­ структурні операнди;

запис.

Операнди є елементарними компонентами, у тому числі формується частина машинної команди, що означає об'єкти, з яких виконується операція. У загальному випадку операнди можуть входити як складові у складніші освіти, звані виразами.

Вирази є комбінації операндів і операторів, що розглядаються як єдине ціле. Результатом обчислення виразу може бути адреса деякої комірки пам'яті або деяке константне (абсолютне) значення.

­ 3 Типи операторів асемблера

Перелічимо можливі типи операторів асемблерата синтаксичні правила формування виразів асемблера:

­ арифметичні оператори;

­ оператори зсуву;

­ оператори порівняння;

­ логічні оператори;

­ індексний оператор;

­ оператор перевизначення типу;

­ оператор перевизначення сегмента;

­ оператор назви типу структури;

­ оператор отримання сегментної складової адреси виразу;

­ оператор отримання усунення виразу.

1 Директиви асемблера

­ Директиви асемблера бувають:

1) Директиви сегментації. Під час попереднього обговорення ми з'ясували всі основні правила запису команд та операндів у програмі на асемблері. Відкритим залишилося питання, як правильно оформити послідовність команд, щоб транслятор міг їх обробити, а мікропроцесор - виконати.

При розгляді архітектури мікропроцесора ми дізналися, що він має шість сегментних регістрів, за допомогою яких може працювати одночасно:

­ з одним сегментом коду;

­ з одним сегментом стеку;

­ з одним сегментом даних;

­ із трьома додатковими сегментами даних.

Фізично сегмент є область пам'яті, зайняту командами та (або) даними, адреси яких обчислюються щодо значення у відповідному сегментному регістрі. Синтаксичне опис сегмента на асемблері є конструкцією, зображену малюнку 13:


­ Рисунок 13 - Синтаксичне опис сегмента на асемблері

Важливо, що функціональне призначення сегмента дещо ширше, ніж просте розбиття програми на блоки коду, даних та стека. Сегментація є частиною більш загального механізму, пов'язаного з модульного програмування концепції.Вона передбачає уніфікацію оформлення об'єктних модулів, створюваних компілятором, зокрема з різних мов програмування. Це дозволяє об'єднувати програми, написані різними мовами. Саме для реалізації різних варіантів такого об'єднання призначені операнди в директиві SEGMENT.

2) Директиви управління лістингом. Директиви управління лістингом поділяються на такі групи:

­ загальні директиви управління лістингом;

­ директиви виведення в лістинг файлів, що включаються;

­ директиви виведення блоків умовного асемблювання;

­ директиви виведення у лістинг макрокоманд;

­ директиви виведення у лістинг інформації про перехресні посилання;

­ директиви зміни формату лістингу

2 Система команд процесора

Система команд процесора представлена ​​малюнку 14.

Розглянемо основні групи команд.

­ Малюнок 14 - Класифікація команд асемблера

Команди бувають:

1 Команди пересилання даних. Ці команди займають дуже важливе місце у системі команд будь-якого процесора. Вони виконують такі найважливіші функції:

­ збереження у пам'яті вмісту внутрішніх регістрів процесора;

­ копіювання вмісту з однієї області пам'яті до іншої;

­ запис у пристрої вводу/виводу та читання з пристроїв вводу/виводу.

У деяких процесорах всі ці функції виконуються єдиною командою MOV (для байтових пересилань - MOVB ) Проте з різними способами адресації операндов.

В інших процесорах крім команди MOV є ще кілька команд до виконання перелічених функций. Також до команд пересилання даних належать команди обміну інформацією (їх позначення будується на основі слова Exchange ). Може бути передбачений обмін інформацією між внутрішніми регістрами, між двома половинами одного регістру ( SWAP ) або між регістром та осередком пам'яті.

2 Арифметичні команди. Арифметичні команди розглядають коди операндів як числові двійкові чи двійково-десяткові коди. Ці команди можуть бути поділені на п'ять основних груп:

­ команди операцій з фіксованою комою (додавання, віднімання, множення, розподіл);

­ команди операцій з плаваючою комою (додавання, віднімання, множення, розподіл);

­ команди очищення;

­ команди інкременту та декременту;

­ команда порівняння.

3 Команди операцій із фіксованою комою працюють із кодами в регістрах процесора чи пам'яті як із звичайними двійковими кодами. Команди операцій з плаваючою комою (точкою) використовують формат подання чисел з порядком і мантисою (зазвичай ці числа займають два послідовні осередки пам'яті). У сучасних потужних процесорахнабір команд з плаваючою комою не обмежується лише чотирма арифметичними діями, а містить і безліч інших складніших команд, наприклад, обчислення тригонометричних функцій, логарифмічних функцій, а також складних функцій, необхідних при обробці звуку та зображення.

4 Команди очищення призначені для запису нульового коду в регістр або комірку пам'яті. Ці команди можуть бути замінені командами пересилання нульового коду, але спеціальні команди очищення зазвичай виконуються швидше, ніж команди пересилання.

5 Команди інкременту (збільшення на одиницю) та декременту

(Зменшення на одиницю) також бувають дуже зручні. Їх можна в принципі замінити командами підсумовування з одиницею або віднімання одиниці, але інкремент і декремент виконуються швидше, ніж підсумовування та віднімання. Ці команди вимагають одного вхідного операнда, який одночасно є вихідним операндом.

6 Команда порівняння призначена для порівняння двох вхідних операндів. По суті, вона обчислює різницю цих двох операндів, але вихідного операнда не формує, а лише змінює біти в регістрі стану процесора за результатом цього віднімання. Наступна за командою порівняння команда (зазвичай це команда переходу) аналізуватиме біти в регістрі стану процесора і виконуватиме дії в залежності від їх значень. У деяких процесорах передбачені команди ланцюжкового порівняння двох послідовностей операндів, що у пам'яті.

7 Логічні команди. Логічні команди виконують над операндами логічні (побітові) операції, тобто розглядають коди операндів як єдине число, бо як набір окремих бітів. Цим вони відрізняються від арифметичних команд. Логічні команди виконують такі основні операції:

­ логічне І, логічне АБО, додавання за модулем 2 (Виключає АБО);

­ логічні, арифметичні та циклічні зрушення;

­ перевірка бітів та операндів;

­ встановлення та очищення бітів (прапорів) регістру стану процесора ( PSW).

Команди логічних операцій дозволяють бітно обчислювати основні логічні функції двох вхідних операндов. Крім того, операція І використовується для примусового очищення заданих бітів (як один з операндів при цьому використовується код маски, в якому розряди, що вимагають очищення, встановлені в нуль). Операція АБО застосовується для примусової установки заданих бітів (як один з операндів при цьому використовується код маски, в якому розряди, що вимагають установки в одиницю, дорівнюють одиниці). Операція «Виключає АБО» використовується для інверсії заданих бітів (як один з операндів при цьому застосовується код маски, в якому біти, що підлягають інверсії, встановлені в одиницю). Команди вимагають двох вхідних операндів та формують один вихідний операнд.

8 Команди зрушень дозволяють бітно зрушувати код операнда вправо (у бік молодших розрядів) або вліво (у бік старших розрядів). Тип зсуву (логічний, арифметичний або циклічний) визначає, яке буде нове значення старшого біта (при зрушенні вправо) або молодшого біта (при зрушенні вліво), а також визначає, чи буде десь збережено колишнє значення старшого біта (при зрушенні вліво) або молодшого біта (при зрушенні праворуч). Циклічні зрушення дозволяють зрушувати біти коду операнда по колу (за годинниковою стрілкою при зрушенні праворуч або проти годинникової стрілки при зрушенні вліво). При цьому кільце зсуву може входити або не входити прапор переносу. У біт прапора перенесення (якщо він використовується) записується значення старшого біта при циклічному зрушенні вліво та молодшого біта при циклічному зрушенні вправо. Відповідно, значення біта прапора перенесення переписуватиметься в молодший розряд при циклічному зрушенні вліво і старший розряд при циклічному зрушенні вправо.

9 Команди переходів. Команди переходів призначені в організацію різноманітних циклів, розгалужень, викликів підпрограм тощо., тобто вони порушують послідовний хід виконання програми. Ці команди записують у регістр-лічильник команд нове значення і тим самим викликають перехід процесора не до наступної по порядку команди, а до будь-якої іншої команди пам'яті програм. Деякі команди переходів передбачають повернення назад, у точку, з якої було зроблено перехід, інші не передбачають цього. Якщо повернення передбачено, поточні параметри процесора зберігаються в стеку. Якщо повернення не передбачене, поточні параметри процесора не зберігаються.

Команди переходів без повернення поділяються на дві групи:

­ команди безумовних переходів;

­ команди умовних переходів

В позначках цих команд використовуються слова Branch (розгалуження) та Jump (стрибок).

Команди безумовних переходів викликають перехід у Нова адресанезалежно ні від чого. Вони можуть викликати перехід на вказану величину зсуву (вперед або назад) або на вказану адресу пам'яті. Величина зміщення або нове значення адреси вказуються як вхідний операнд.

Команди умовних переходів викликають перехід який завжди, лише за виконанні заданих умов. Як такі умови зазвичай виступають значення прапорів у регістрі стану процесора ( PSW ). Тобто умовою переходу є результат попередньої операції, яка змінює значення прапорів. Усього таких умов переходу може бути від 4 до 16. Декілька прикладів команд умовних переходів:

­ перехід, якщо дорівнює нулю;

­ перехід, якщо не дорівнює нулю;

­ перехід, якщо є переповнення;

­ перехід, якщо немає переповнення;

­ перехід, якщо більше за нуль;

­ перехід, якщо менше або дорівнює нулю.

Якщо умова переходу виконується, проводиться завантаження в регістр-лічильник команд нового значення. Якщо ж умова переходу не виконується, лічильник команд просто нарощується, і процесор вибирає та виконує наступну по порядку команду.

Спеціально для перевірки умов переходу застосовується команда порівняння (СМР), що передує команді умовного переходу (або навіть кільком командам умовних переходів). Але прапори можуть встановлюватися і будь-якою іншою командою, наприклад, командою пересилання даних, будь-якою арифметичною або логічною командою. Зазначимо, що самі команди переходів прапори не змінюють, що й дозволяє ставити кілька команд переходів одну за одною.

Особливе місце серед команд переходу із поверненням займають команди переривань. Ці команди в якості вхідного операнда вимагають номер переривання (адреса вектора).

Висновок:

Мова асемблера – це символічне уявлення машинної мови. Мова асемблера для кожного типу комп'ютера свій. Програма на асемблері є сукупність блоків пам'яті, званих сегментами пам'яті. Кожен сегмент містить сукупність речень мови, кожна з яких займає окремий рядок коду програми. Пропозиції асемблера бувають чотирьох типів: команди чи інструкції, макрокоманди, директиви, рядки коментарів.

Допустимими символами при написанні тексту програм є всі латинські літери: A-Z,a-z. При цьому великі та малі літери вважаються еквівалентними; цифри від 0 до 9 ; знаки ? , @ , $ , _ , & ; роздільники , . () < > { } + / * % ! " " ? = # ^ .

Застосовують такі типи операторів асемблера та синтаксичні правила формування виразів асемблера. арифметичні оператори, оператори зсуву, оператори порівняння, логічні оператори, індексний оператор, оператор перевизначення типу, оператор перевизначення сегмента, оператор іменування типу структури, оператор отримання сегментної складової адреси виразу, оператор отримання зміщення виразу.

Система команд поділена на 8 основних груп.

­ Контрольні питання:

1 Що є мовою асемблера?

2 Які символи можна використовувати для запису команд на асемблері?

3 Що являють собою мітки та їх призначення?

4 Пояснити структуру команд асемблера.

5 Перерахувати 4 типи пропозицій асемблера.

НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ УЗБЕКІСТАНУ ІМЕНІ СВІТУ УЛУГБЕКУ

ФАКУЛЬТЕТ КОМП'ЮТЕРНОЇ ТЕХНОЛОГІЇ

На тему: Семантичний аналіз EXE-файлу.

Виконав:

Ташкент 2003 року.

Передмова.

Мова асемблера та структура команд.

Структура EXE-файлу (семантичний аналіз).

Структура COM-файлу.

Принцип дії та поширення вірусу.

Дисасемблер.

програми.

Передмова

Професія програміста дивовижна та унікальна. Нині науку життя й неможливо уявити без нових технологій. Все що пов'язане з діяльністю людини не обходиться без обчислювальної техніки. А це сприяє її високому розвитку та досконалості. Нехай розвиток персональних комп'ютерів почався нещодавно, але протягом цього часу були зроблені колосальні кроки по програмним продуктам і ще довгий час ці продукти широко використовуватимуться. Область пов'язаних з комп'ютерами знань зазнала вибуху, як і відповідна технологія. Якщо не брати до розгляду комерційну сторону, то можна сказати, що чужих людей у ​​цій галузі професійної діяльності немає. Багато хто займається розробкою програм не заради вигоди чи заробітку, а з власної волі, захоплення. Звичайно це не позначиться на якості програми, і в цій справі «бізнесі» є конкуренція та попит на якість виконання, на стабільній роботі і відповідає всім вимогам сучасності. Тут також варто відзначити появу мікропроцесорів у 60-х роках, які прийшли на заміну великої кількості набору ламп. Є деякі різновиди мікропроцесорів, які сильно відрізняються один від одного. Ці мікропроцесори відмінні один від одного розрядністю та вбудованими системними командами. Найпоширеніші такі як: Intel, IBM, Celeron, AMD тощо. Всі ці процесори стосуються розвиненої архітектури процесорів фірми Intel. Поширення мікрокомп'ютерів спричинило перегляд відносини до мови асемблера з двох основних причин. По-перше, програми, написані мовою асемблера, вимагають значно менше пам'яті та часу виконання. По-друге, знання мови асемблера та результуючого машинного коду дає розуміння архітектури машини, що навряд чи забезпечується під час роботи мовою високого рівня. Хоча більшість фахівців у галузі програмного забезпечення ведуть розробки мовами високого рівня, таких як Паскаль, С або Delphi, що простіше при написанні програм, найбільш потужне та ефективне програмне забезпеченняповністю або частково написано мовою асемблера. Мови високого рівня були розроблені для того, щоб уникнути спеціальної технічної особливостіконкретні комп'ютери. А мова асемблера, у свою чергу, розроблена для конкретної специфіки процесора. Отже, щоб написати програму мовою асемблера для конкретного комп'ютера, слід знати його архітектуру. В даний час видом основного програмного продуктує EXE-файл. Враховуючи позитивні стороницього автор програми може бути впевнений у її недоторканності. Але часто це далеко не так. Існує так само і дисасемблер. За допомогою дисассемблера можна дізнатися про переривання та коди програми. Людині, яка добре знається на асемблері не складно буде переробити всю програму на свій смак. Можливо звідси виникає найнерозв'язніша проблема – вірус. Навіщо люди пишуть вірус? Деякі ставлять це питання з подивом, деякі зі злістю, але продовжують існувати люди, які цікавляться цим завданням не з точки зору завдання якоїсь шкоди, а як інтересу до системного програмування. Пишуть Віруси різних причин. Одним подобається системні виклики, іншим удосконалювати свої знання в асемблері. Про все це я постараюся викласти у своїй курсової роботи. Також у ньому сказано як про структуру EXE-файлу а й про мову асемблера.

^ Мова Асемблера.

Цікаво простежити, починаючи з часу появи перших комп'ютерів і закінчуючи сьогоденням, за трансформаціями уявлень про мову асемблера у програмістів.

Колись асемблер був мовою, без знання якої не можна було змусити комп'ютер зробити щось корисне. Поступово ситуація змінювалась. З'являлися зручніші засоби спілкування з комп'ютером. Але, на відміну інших мов, асемблер не вмирав, навіть він міг зробити цього у принципі. Чому? У пошуках відповіді спробуємо зрозуміти, що таке мова асемблера взагалі.

Якщо коротко, то мова асемблера – це символічне уявлення машинної мови. Всі процеси в машині на найнижчому апаратному рівні приводяться в дію тільки командами (інструкціями) машинної мови. Звідси зрозуміло, що, незважаючи на загальну назву, мова асемблера для кожного типу комп'ютера своя. Це стосується і зовнішнього виглядупрограм, написаних на асемблері, та ідей, відображенням яких ця мова є.

По-справжньому розв'язати проблеми, пов'язані з апаратурою (або навіть, залежать від апаратури як, наприклад, підвищення швидкодії програми), неможливо без знання асемблера.

Програміст або будь-який інший користувач може використовувати будь-які високорівневі засоби, аж до програм побудови віртуальних світів і, можливо, навіть не підозрювати, що насправді комп'ютер виконує не команди мови, якою написана його програма, а їх трансформоване уявлення у формі нудної та похмурої Послідовність команд зовсім іншої мови - машинної. А тепер уявімо, що у такого користувача виникла нестандартна проблема або просто щось не склалося. Наприклад, його програма повинна працювати з деяким незвичайним пристроєм або виконувати інші дії, що вимагають знання принципів роботи комп'ютера. Яким би розумним не був програміст, якою б гарною не була мова, якою він написав свою чудову програму, без знання асемблера йому не обійтися. І невипадково практично всі компілятори мов високого рівня містять засоби зв'язку своїх модулів з модулями на асемблері або підтримують вихід асемблерний рівень програмування.

Звичайно, час комп'ютерних універсалів уже минув. Як кажуть не можна осягнути неосяжне. Але є щось спільне, своєрідний фундамент, на якому будується будь-яка серйозна комп'ютерна освіта. Це знання про принципи роботи комп'ютера, його архітектуру та мову асемблера як відображення та втілення цих знань.

Типовий сучасний комп'ютер (на базі i486 чи Pentium) складається з наступних компонентів (рис. 1).

Мал. 1. Комп'ютер та периферійні пристрої

Мал. 2. Структурна схема персонального комп'ютера

З малюнка (рис 1) видно, що комп'ютер складається з кількох фізичних пристроїв, кожне з яких підключено одного блоку, званому системним. Якщо міркувати логічно, то ясно, що він відіграє роль деякого пристрою, що координує. Давайте заглянемо всередину системного блоку(Не потрібно намагатися проникнути всередину монітора - там немає нічого цікавого, до того ж це небезпечно): відкриваємо корпус і бачимо якісь плати, блоки, проводи. Щоб зрозуміти їхнє функціональне призначення, подивимося на структурну схему типового комп'ютера (рис. 2). Вона не претендує на безумовну точність і має на меті лише показати призначення, взаємозв'язок та типовий склад елементів сучасного персонального комп'ютера.

Обговоримо схему на рис. 2 у дещо нетрадиційному стилі.
Людині властиво, зустрічаючись із чимось новим, шукати якісь асоціації, які можуть допомогти йому пізнати невідоме. Які асоціації викликає комп'ютер? У мене, наприклад, комп'ютер часто асоціюється із самою людиною. Чому?

Людина створюючи комп'ютер десь у глибині себе думав що створює щось схоже на себе саму. Комп'ютер має органи сприйняття інформації із зовнішнього світу - це клавіатура, миша, накопичувачі на магнітних дисках. На рис. 2 ці органи розташовані праворуч від системних шин. Комп'ютер має органи, що “перетравлюють” отриману інформацію - це центральний процесорі оперативна пам'ять. І, нарешті, комп'ютер має органи мови, що видають результати переробки. Це також деякі з пристроїв праворуч.

Сучасним комп'ютерамзвичайно, далеко до людини. Їх можна порівняти з істотами, що взаємодіють із зовнішнім світом на рівні великого, але обмеженого набору безумовних рефлексів.
Цей набір рефлексів утворює систему машинних команд. На якому високому рівні ви спілкувалися з комп'ютером, зрештою все зводиться до нудної і одноманітної послідовності машинних команд.
Кожна машинна команда є своєрідним подразником для збудження того чи іншого безумовного рефлексу. Реакція цей подразник завжди однозначна і “зашита” у блоці мікрокоманд як мікропрограми. Ця мікропрограма і реалізує дії щодо реалізації машинної команди, але вже на рівні сигналів, що подаються на ті чи інші логічні схемикомп'ютера, цим керуючи різними підсистемами комп'ютера. У цьому полягає так званий принцип мікропрограмного керування.

Продовжуючи аналогію з людиною, зазначимо: для того, щоб комп'ютер правильно харчувався, придумано безліч операційних систем, компіляторів сотень мов програмування і т. д. шлунку (комп'ютеру). Тільки шлунок комп'ютера любить дієтичну, одноманітну їжу - подавай йому структуровану інформацію, у вигляді строго організованих послідовностей нулів і одиниць, комбінації яких і складають машинну мову.

Таким чином, зовні будучи поліглотом, комп'ютер розуміє лише одну мову – мову машинних команд. Звичайно, для спілкування та роботи з комп'ютером необов'язково знати цю мову, але практично будь-який професійний програміст рано чи пізно стикається з необхідністю його вивчення. На щастя, програмісту не потрібно намагатися осягнути значення різних комбінацій двійкових чисел, оскільки ще в 50-ті роки програмісти почали використовувати для програмування символічний аналог машинної мови, який назвали мовою асемблера. Ця мова точно відбиває всі особливості машинної мови. Саме тому, на відміну від мов високого рівня, мова асемблера для кожного типу комп'ютера своя.

З усього вищесказаного можна дійти невтішного висновку, що, оскільки мова асемблера для комп'ютера “рідний”, те й найефективніша програма може бути написана лише у ньому (за умови, що її пише кваліфікований програміст). Тут є одне маленьке “але”: це дуже трудомісткий процес, що вимагає великої уваги та практичного досвіду. Тому реально на асемблері пишуть переважно програми, які мають забезпечити ефективну роботуз апаратною частиною. Іноді на асемблері пишуться критичні за часом виконання чи витрачання пам'яті ділянки програми. Згодом вони оформляються у вигляді підпрограм та поєднуються з кодом мовою високого рівня.

До вивчення мови асемблера будь-якого комп'ютера має сенс приступати тільки після з'ясування того, яка частина комп'ютера залишена видимою та доступною для програмування цією мовою. Це так звана програмна модель комп'ютера, частиною якої є програмна модель мікропроцесора, яка містить 32 регістри в тій чи іншій мірі доступні для використання програмістом.

Дані регістри можна розділити на великі групи:

^ 16 користувальницьких регістрів;

16 системних регістрів.

У програмах мовою асемблера регістри використовуються дуже інтенсивно. Більшість регістрів мають певне функціональне призначення.

Як випливає з назви, регістри користувача називаються тому, що програміст може використовувати їх при написанні своїх програм. До цих регістрів відносяться (рис. 3):

Вісім 32-бітових регістрів, які можуть використовуватися програмістами для зберігання даних та адрес (їх ще називають регістрами загального призначення (РОН)):

шість регістрів сегментів: cs, ds, ss, es, fs, gs;

регістри стану та управління:

Реєстр прапорів eflags/flags;

Реєстр покажчика команди eip/ip.

Мал. 3. Регістри користувача мікропроцесорів i486 і Pentium

Чому багато хто з цих регістрів наведено з похилою роздільною рисою? Ні, це не різні регістри – це частини одного великого 32-розрядного регістру. Їх можна використовувати у програмі як окремі об'єкти. Так зроблено задля забезпечення працездатності програм, написаних молодших 16-разрядных моделей мікропроцесорів фірми Intel, починаючи з i8086. Мікропроцесори i486 і Pentium мають переважно 32-розрядні регістри. Їх кількість, за винятком сегментних регістрів, така сама, як і у i8086, але розмірність більша, що й відображено в їх позначеннях - вони мають
приставку e (Extended).

^ Реєстри загального призначення
Усі регістри цієї групи дозволяють звертатися до своїх “молодших” частин (див. рис. 3). Розглядаючи цей малюнок, зауважте, що використовувати для самостійної адресації можна лише молодші 16 та 8-бітні частини цих регістрів. Старші 16 біт цих регістрів як самостійні об'єкти недоступні. Це зроблено, як ми зазначили, для сумісності з молодшими 16-розрядними моделями мікропроцесорів фірми Intel.

Перерахуємо регістри, які стосуються групи регістрів загального призначення. Оскільки ці регістри фізично перебувають у мікропроцесорі всередині арифметико-логического устрою (АЛУ), їх ще називають регістрами АЛУ:

eax/ax/ah/al (Accumulator register) – акумулятор.
Застосовується для зберігання проміжних даних. У деяких командах використання цього регістру є обов'язковим;

ebx/bx/bh/bl (Base register) – базовий регістр.
Застосовується для зберігання базової адреси деякого об'єкта пам'яті;

ecx/cx/ch/cl (Count register) – регістр-лічильник.
Застосовується в командах, які роблять деякі дії, що повторюються. Його використання найчастіше неявно та приховано в алгоритмі роботи відповідної команди.
Наприклад, команда організації циклу loop крім передачі управління команді, що перебуває за деякою адресою, аналізує та зменшує на одиницю значення регістра ecx/cx;

edx/dx/dh/dl (Data register) – регістр даних.
Так само, як і регістр eax/ax/ah/al, він зберігає проміжні дані. У деяких командах використання обов'язково; для деяких команд це відбувається неявно.

Наступні два регістри використовуються для підтримки так званих ланцюжкових операцій, тобто операцій, які проводять послідовну обробку ланцюжків елементів, кожен з яких може мати довжину 32, 16 або 8 біт:

esi/si (Source Index register) – індекс джерела.
Цей регістр у ланцюжкових операціях містить поточну адресу елемента в ланцюжку-джерелі;

edi/di (Destination Index register) – індекс приймача (одержувача).
Цей регістр у ланцюжкових операціях містить поточну адресу в ланцюжку-приймачі.

У архітектурі мікропроцесора на програмно-апаратному рівні підтримується така структура даних, як стек. Для роботи зі стеком у системі команд мікропроцесора є спеціальні команди, а в програмної моделімікропроцесора для цього існують спеціальні регістри:

esp/sp (Stack Pointer register) - регістр покажчика стека.
Містить вказівник вершини стека у поточному сегменті стека.

ebp/bp (Base Pointer register) - регістр покажчика бази кадру стека.
Призначений для організації довільного доступу до даних усередині стека.

Стеком називають область програми для тимчасового зберігання довільних даних. Зрозуміло, дані можна зберігати і в сегменті даних, проте в цьому випадку для кожного зберігається на час даного треба заводити окрему іменовану комірку пам'яті, що збільшує розмір програми та кількість імен, що використовуються. Зручність стека полягає в тому, що його область використовується багаторазово, причому збереження в стеку даних і вибірка звідти виконується за допомогою ефективних команд push і pop без вказівок будь-яких імен.
Стек традиційно використовується, наприклад, для збереження вмісту регістрів, що використовуються програмою, перед викликом підпрограми, яка, у свою чергу, використовуватиме регістри процесора "у своїх особистих цілях". Вихідний вміст регістрів витікається зі стека після повернення з підпрограми. Інший поширений прийом - передача підпрограмі необхідних нею параметрів через стек. Підпрограма, знаючи, в якому порядку поміщені в стек параметри, може забрати їх звідти та використовувати під час виконання. Відмінною особливістюстека є своєрідний порядок вибірки які у ньому даних: у час в стеку доступний лише верхній елемент, тобто. елемент, завантажений у стек останнім. Вивантаження зі стека верхнього елемента робить доступним наступний елемент. Елементи стека розташовуються в області пам'яті, відведеної під стек, починаючи з дна стека (тобто з його максимальної адреси) за адресами, що послідовно зменшуються. Адреса верхнього доступного елемента зберігається в регістрі-покажчику стека SP. Як і будь-яка інша область пам'яті програми, стек повинен входити до якогось сегмента або утворювати окремий сегмент. У будь-якому випадку сегментна адреса цього сегмента міститься в сегментний регістр стека SS. Таким чином, пара регістрів SS:SP описують адресу доступного осередку стека: в SS зберігається сегментний адресу стека, а в SP - зміщення останнього збереженого в стеку даного (рис. 4, а). Звернемо увагу на те, що у вихідному стані покажчик стека SP вказує на комірку, що лежить під дном стека і не входить до нього.

Рис 4. Організація стека: а - вихідний стан, б - після завантаження одного елемента (у даному прикладі - вмісту регістру АХ), - після завантаження другого елемента (вмісту регістру DS), г - після вивантаження одного елемента, д - після вивантаження двох елементів та повернення у вихідний стан.

Завантаження у стек здійснюється спеціальною командою роботи зі стеком push (проштовхнути). Ця команда спочатку зменшує на 2 вміст покажчика стека, а потім поміщає операнд за адресою SP. Якщо, наприклад, ми хочемо тимчасово зберегти в стеку вміст регістру АХ, слід виконати команду

Стек перетворюється на стан, показане на рис. 1.10 б. Видно, що покажчик стека зміщується на два байти вгору (у бік менших адрес) і на цю адресу записується вказаний в команді проштовхування операнд. Наступна команда завантаження в стек, наприклад,

переведе стек у стан, показаний на рис. 1.10 ст. У стеку тепер зберігатимуться два елементи, причому доступним буде тільки верхній, на який вказує покажчик стека SP. Якщо через деякий час нам знадобилося відновити вихідний вміст збережених у стеку регістрів, ми повинні виконати команди вивантаження зі стеку pop (виштовхнути):

pop DS
pop AX

Якого розміру має бути стек? Це залежить від того, наскільки інтенсивно він використовується у програмі. Якщо, наприклад, планується зберігати в стеку масив об'ємом 10 000 байт, то стек повинен бути не меншим за цей розмір. При цьому треба мати на увазі, що в ряді випадків стек автоматично використовується системою, зокрема, при виконанні команди переривання int 21h. По цій команді спочатку процесор поміщає в стек адресу повернення, а потім DOS відправляє туди вміст регістрів та іншу інформацію, що відноситься до перерваної програми. Тому, навіть якщо програма зовсім не використовує стек, він все ж таки повинен бути присутнім у програмі і мати розмір не менше кількох десятків слів. У першому прикладі ми відвели під стек 128 слів, що безумовно достатньо.

^ Структура програми на асемблері

Програма на асемблері є сукупність блоків пам'яті, званих сегментами пам'яті. Програма може складатися з одного або кількох блоків-сегментів. Кожен сегмент містить сукупність речень мови, кожна з яких займає окремий рядок коду програми.

Пропозиції асемблера бувають чотирьох типів:

команди або інструкції, що є символічними аналогами машинних команд. У процесі трансляції інструкції асемблера перетворюються на відповідні команди системи команд мікропроцесора;

макрокоманди - оформлювані певним чином речення тексту програми, що заміщуються під час трансляції іншими реченнями;

директиви, що є вказівкою транслятора асемблера виконання деяких дій. У директив немає аналогів у машинному поданні;

рядки коментарів, що містять будь-які символи, у тому числі літери російського алфавіту. Коментарі ігноруються транслятором.

^ Синтаксис асемблера

Пропозиції, що становлять програму, можуть бути синтаксичною конструкцією, що відповідає команді, макрокоманді, директиві або коментарю. Для того, щоб транслятор асемблера міг розпізнати їх, вони повинні формуватися за певними синтаксичними правилами. Для цього найкраще використовувати формальний опис синтаксису мови на кшталт правил граматики. Найбільш поширені способи подібного опису мови програмування – синтаксичні діаграми та розширені форми Бекуса-Наура. Для практичного використання зручніші синтаксичні діаграми. Наприклад, синтаксис речень асемблера можна описати за допомогою синтаксичних діаграм, показаних на наступних малюнках.

Мал. 5. Формат пропозиції асемблера

Мал. 6. Формат директив

Мал. 7. Формат команд та макрокоманд

На цих малюнках:

ім'я мітки - ідентифікатор, значенням якого є адреса першого байта пропозиції вихідного тексту програми, яке він позначає;

ім'я - ідентифікатор, який відрізняє цю директиву від інших однойменних директив. Через війну обробки асемблером певної директиви цього імені може бути присвоєно певні характеристики;

код операції (КОП) та директива – це мнемонічні позначення відповідної машинної команди, макрокоманди або директиви транслятора;

операнди - частини команди, макрокоманди чи директиви асемблера, що позначають об'єкти, з яких виконуються дії. Операнди асемблера описуються виразами з числовими та текстовими константами, мітками та ідентифікаторами змінних з використанням знаків операцій та деяких зарезервованих слів.

^ Як використовувати синтаксичні діаграми? Дуже просто: для цього потрібно лише знайти і потім пройти шлях від входу діаграми (ліворуч) до її виходу (праворуч). Якщо такий шлях існує, то пропозиція чи конструкція синтаксично правильні. Якщо такого шляху немає, то цю конструкцію компілятор не прийме. При роботі з синтаксичними діаграмами звернемо увагу на напрямок обходу, що вказується стрілками, оскільки серед шляхів можуть бути такі, якими можна йти праворуч наліво. Власне, синтаксичні діаграми відбивають логіку роботи транслятора під час аналізу вхідних пропозицій програми.

Допустимими символами при написанні тексту програм є:

Усі латинські літери: A-Z, a-z. При цьому великі та малі літери вважаються еквівалентними;

Цифри від 0 до 9;

Знаки?, @, $, _, &;

Розділювачі, . ()< > { } + / * % ! " " ? \ = # ^.

Пропозиції асемблера формуються з лексем, що є синтаксично нероздільні послідовності допустимих символів мови, що мають сенс для транслятора.

Лексемами є:

ідентифікатори - послідовності допустимих символів, що використовуються для позначення таких об'єктів програми, як коди операцій, імена змінних та назви міток. Правило запису ідентифікаторів полягає в наступному: ідентифікатор може складатися з одного або кількох символів. Як символи можна використовувати літери латинського алфавіту, цифри та деякі спеціальні знаки - _, ?, $, @. Ідентифікатор не може починатися символом цифри. Довжина ідентифікатора може бути до 255 символів, хоча транслятор сприймає лише перші 32, а інші ігнорує. Регулювати довжину можливих ідентифікаторів можна за допомогою опції командного рядка mv. Крім цього існує можливість вказати транслятору на те, щоб він розрізняв великі і малі літери або ігнорував їхню відмінність (що і робиться за умовчанням).

^ Команди асемблера.

Команди асемблера розкривають можливість передавати комп'ютеру свої вимоги, механізм передачі управління у програмі (цикли та переходи) для логічних порівнянь та програмної організації. Проте, програмовані завдання рідко бувають такі прості. Більшість програм містять ряд циклів, у яких кілька команд повторюються до досягнення певної вимоги, та різні перевірки, які визначають, які з кількох дій слід виконувати. Деякі команди можуть передавати управління, змінюючи нормальну послідовність кроків безпосередньою модифікацією значення зміщення командного покажчика. Як говорилося раніше, існують різні команди для різних процесорів, ми будемо розглядати ряд деяких команд для процесорів 80186, 80286 і 80386.

Для опису стану прапорів після виконання деякої команди використовувати вибірку з таблиці, що відображає структуру регістру прапорів eflags:

У нижньому рядку цієї таблиці наведено значення прапорів після виконання команди. При цьому використовуються такі позначення:

1 - після виконання команди прапор встановлюється (рівний 1);

0 - після виконання команди прапор скидається (рівний 0);

r – значення прапора залежить від результату роботи команди;

Після виконання команди прапор не визначено;

пробіл - після виконання команди прапор не змінюється;

Для представлення операндів у синтаксичних діаграмах використовуються такі позначення:

r8, r16, r32 - операнд в одному з регістрів розміром байт, слово або подвійне слово;

m8, m16, m32, m48 - операнд у пам'яті розміром байт, слово, подвійне слово або 48 біт;

i8, i16, i32 - безпосередній операнд розміром байт, слово чи подвійне слово;

a8, a16, a32 - відносна адреса (зміщення) у сегменті коду.

Команди (за абеткою):

*Дані команди докладно описані.

ADD
(ADDition)

Додавання

^ Схема команди:

add приймач, джерело

Призначення: додавання двох операндів джерело та приймач розмірністю байт, слово або подвійне слово.

Алгоритм роботи:

скласти операнди джерело та приймач;

записати результат додавання до приймача;

встановити прапори.

Стан прапорів після виконання команди:

Застосування:
Команда add використовується для складання двох цілих операндів. Результат додавання міститься за адресою першого операнда. Якщо результат додавання виходить за межі операнда приймач (виникає переповнення), то врахувати цю ситуацію слід шляхом аналізу прапора cf та подальшого можливого застосування команди adc. Наприклад, складемо значення в регістрі ax та області пам'яті ch. При додаванні слід врахувати можливість переповнення.

Регістр плюс регістр чи пам'ять:

|000000dw|modregr/rm|

Регістр AX (AL) плюс безпосереднє значення:

|0000010w|--data--|data, якщо w=1|

Регістр або пам'ять плюс безпосереднє значення:

|100000sw|mod000r/m|--data--|data, якщо BW=01|

CALL
(CALL)

Виклик процедури чи завдання

^ Схема команди:

Призначення:

передача управління близькою чи далекою процедурою із запам'ятовуванням у стеку адреси точки повернення;

перемикання завдань.

Алгоритм роботи:
визначається типом операнда:

Мітка ближня - у стек заноситься вміст покажчика команд eip/ip і до цього ж регістр завантажується нове значення адреси, відповідне мітці;

Мітка дальня - в стек заноситься вміст покажчика команд eip/ip та cs. Потім ці ж регістри завантажуються нові значення адрес, відповідні дальньої мітці;

R16, 32 або m16, 32 - визначають регістр або комірку пам'яті, що містять усунення в поточному сегменті команд, куди передається управління. При передачі управління у стек заноситься вміст покажчика команд eip/ip;

Покажчик на пам'ять - визначає комірку пам'яті, що містить 4 або 6-байтний покажчик на процедуру, що викликається. Структура такого покажчика 2+2 або 2+4 байти. Інтерпретація такого покажчика залежить від режиму роботи мікропроцесора:

^ Стан прапорів після виконання команди (крім перемикання задачі):

виконання команди не впливає на прапори

При перемиканні задачі значення прапорців змінюються відповідно до інформації про регістр eflags в сегменті стану TSS задачі, на яку здійснюється перемикання.
Застосування:
Команда call дозволяє організувати гнучку та багатоваріантну передачу управління на підпрограму із збереженням адреси точки повернення.

Об'єктний код (чотири формати):

Пряма адресація у сегменті:

|11101000|disp-low|diep-high|

Непряма адресація у сегменті:

|11111111|mod010r/m|

Непряма адресація між сегментами:

|11111111|mod011r/m|

Пряма адресація між сегментами:

|10011010|offset-low|offset-high|seg-low|seg-high|

CMP
(Compare operands)

Порівняння операндів

^ Схема команди:

cmp операнд1,операнд2

Призначення: порівняння двох операндів.

Алгоритм роботи:

виконати віднімання (операнд1-операнд2);

залежно від результату встановити прапори, операнд1 та операнд2 не змінювати (тобто результат не запам'ятовувати).

Застосування:
Ця командавикористовується для порівняння двох операндів методом віднімання, при цьому операнди не змінюються. За результатами виконання команди встановлюються прапори. Команда cmp застосовується з командами умовного переходу та командою встановлення байта за значенням setcc.

Об'єктний код (три формати):

Реєстр або пам'ять з регістром:

|001110dw|modregr/m|

Безпосереднє значення з регістром AX (AL):

|0011110w|--data--|data, якщо w=1|

Безпосереднє значення з регістром або пам'яттю:

|100000sw|mod111r/m|--data--|data, якщо sw=0|

DEC
(DECrement operand by 1)

Зменшення операнда на одиницю

^ Схема команди:

dec операнд

Призначення: зменшення значення операнда у пам'яті чи регістрі на 1.

Алгоритм роботи:
команда віднімає 1 з операнда. Стан прапорів після виконання команди:

Застосування:
Команда dec використовується зменшення значення байта, слова, подвійного слова у пам'яті чи регістрі на одиницю. При цьому зауважте, що команда не впливає на прапор cf.

Реєстр: |01001reg|

^ Регістр чи пам'ять: |1111111w|mod001r/m|

DIV
(DIVide unsigned)

Поділ беззнаковий

Схема команди:

div дільник

Призначення: виконання операції поділу двох двійкових знакових значень.

^ Алгоритм роботи:
Для команди необхідне завдання двох операндів - дільника та дільника. Ділим задається неявно і розмір його залежить від розміру дільника, який вказується в команді:

якщо дільник розміром байт, то ділене має бути розташоване в регістрі ax. Після операції приватне міститься в al, а залишок - в ah;

якщо дільник розміром у слово, то ділене має бути розташоване в парі регістрів dx:ax, причому молодша частина поділеного знаходиться в ax. Після операції приватне міститься в ax, а залишок - в dx;

якщо дільник розміром подвійне слово, то ділене має бути розташоване в парі регістрів edx:eax, причому молодша частина діленого знаходиться в eax. Після операції приватне міститься в eax, а залишок - в edx.

^ Стан прапорів після виконання команди:

Застосування:
Команда виконує цілий поділ операндів з видачею результату поділу у вигляді приватного та залишку від поділу. За виконання операції поділу можливе виникнення виняткової ситуації: 0 - помилка поділу. Ця ситуація виникає в одному з двох випадків: дільник дорівнює 0 або приватне занадто велике для його розміщення в регістрі eax/ax/al.

Об'єктний код:

|1111011w|mod110r/m|

INT
(INTerrupt)

Виклик підпрограми обслуговування переривання

^ Схема команди:

int номер_переривання

Призначення: виклик підпрограми обслуговування переривання з номером переривання, заданим операндом команди.

^ Алгоритм роботи:

записати в стек регістр прапорів eflags/flags та адресу повернення. При записі адреси повернення спочатку записується вміст сегментного регістру cs, потім вміст покажчика команд eip/ip;

скинути у нуль прапори if та tf;

передати керування на програму обробки переривання із зазначеним номером. Механізм передачі керування залежить від режиму роботи мікропроцесора.

^ Стан прапорів після виконання команди:

Застосування:
Як видно із синтаксису, існують дві форми цієї команди:

int 3 має свій індивідуальний код операції 0cch і займає один байт. Ця обставина робить її дуже зручною для використання в різних програмних відладчиках для встановлення точок переривання шляхом заміни першого байта будь-якої команди. Мікропроцесор, зустрічаючи в послідовності команд команду з кодом операції 0cch викликає програму обробки переривання з номером вектора 3, яка служить для зв'язку з програмним відладчиком.

Друга форма команди займає два байти, має код операції 0cdh та дозволяє ініціювати виклик підпрограми обробки переривання з номером вектора в діапазоні 0–255. Особливості передачі управління, як було зазначено, залежить від режиму роботи мікропроцесора.

Об'єктний код (два формати):

Реєстр: |01000reg|

^ Регістр чи пам'ять: |1111111w|mod000r/m|

JCC
JCXZ/JECXZ
(Jump if condition)

(Jump if CX=Zero/Jump if ECX=Zero)

Перехід, якщо виконано умову

Перехід, якщо CX/ECX дорівнює нулю

^ Схема команди:

jcc мітка
jcxz мітка
jecxz мітка

Призначення: перехід у поточному сегменті команд залежно від певної умови.

^ Алгоритм роботи команд (крім jcxz/jecxz):
Перевірка стану прапорів залежно від коду операції (воно відображає умову, що перевіряється):

якщо умову, що перевіряється, істинно, то перейти до осередку, позначеного операндом;

якщо умова, що перевіряється, хибно, то передати управління наступній команді.

Алгоритм роботи команди jcxz/jecxz:
Перевірка умови рівності нулю вмісту регістру ecx/cx:

якщо перевіряється умов

Програмування лише на рівні машинних команд - це мінімальний рівень, у якому можливе складання програм. Система машинних команд повинна бути достатньою для того, щоб реалізувати необхідні дії, видаючи вказівки апаратури обчислювальної машини.

Кожна машинна команда складається із двох частин:

  • операційною – визначальною, «що робити»;
  • операндної - визначальною об'єкти обробки, "з чим робити".

Машинна команда мікропроцесора, записана мовою асемблера, є одним рядком, що має наступний синтатичний вигляд:

мітка команда/директива операнд(и); коментарі

При цьому обов'язковим полем у рядку є команда чи директива.

Мітка, команда/директива та операнди (якщо є) поділяються принаймні одним символом пробілу або табуляції.

Якщо команду або директиву необхідно продовжити на наступному рядку, використовується символ зворотний слєш: \.

За замовчуванням мова асемблера не розрізняє великі та малі літери в написанні команд або директив.

Приклади рядків коду:

Count db 1 ;Ім'я, директива, один операнд
mov eax,0 ;Команда, два операнди
cbw; Команда

Мітки

Мітка у мові асемблера може містити такі символи:

  • усі літери латинського алфавіту;
  • цифри від 0 до 9;
  • спецсимволи: _, @, $, ?.

В якості першого символу мітки може використовуватися точка, але деякі компілятори не рекомендують використовувати цей знак. Як позначки не можна використовувати зарезервовані імена Асемблера (директиви, оператори, імена команд).

Першим символом у мітці має бути буква або спецсимвол (але не цифра). Максимальна довжинамітки – 31 символ. Усі мітки, які записуються в рядку, що не містить директиви асемблера, повинні закінчуватися двокрапкою: .

Команди

Команда вказує транслятору, яку дію має виконати мікропроцесор. У сегменті даних команда (або директива) визначає поле, робочу область чи константу. У сегменті коду команда визначає дію, наприклад, пересилання (mov) або додавання (add).

Директиви

Асемблер має ряд операторів, які дозволяють керувати процесом асемблювання та формування лістингу. Ці оператори називаються директивами . Вони діють лише в процесі асемблювання програми та, на відміну від команд, не генерують машинних кодів.

Операнди

Операнд – об'єкт, над яким виконується машинна команда чи оператор мови програмування.
Команда може мати один або два операнди, або взагалі не мати операндів. Число операндів неявно задається кодом команди.
Приклади:

  • Немає операндів ret ;Повернутись
  • Один операнд inc ecx; Збільшити ecx
  • Два операнди add eax,12 ;Додати 12 до eax

Мітка, команда (директива) та операнд не обов'язково повинні починатися з певної позиції в рядку. Однак рекомендується записувати їх у стовпчик для більшої зручності читання програми.

Як операнди можуть виступати

  • ідентифікатори;
  • ланцюжки символів, укладених у одинарні чи подвійні лапки;
  • цілі числа у двійковій, вісімковій, десятковій або шістнадцятковій системі числення.
Ідентифікатори

Ідентифікатори – послідовності допустимих символів, які використовуються для позначення таких об'єктів програми, як коди операцій, імена змінних та назви міток.

Правила запису ідентифікаторів.

  • Ідентифікатор може складатися з одного або кількох символів.
  • Як символи можна використовувати літери латинського алфавіту, цифри та деякі спеціальні знаки: _, ?, $, @.
  • Ідентифікатор не може починатися символом цифри.
  • Довжина ідентифікатора може бути 255 символів.
  • Транслятор сприймає перші 32 символи ідентифікатора, інші ігнорує.
Коментарі

Коментарі відокремлюються від рядка, що виконується символом; . При цьому все, що записано після символу крапка з комою і до кінця рядка, є коментарем. Використання коментарів у програмі покращує її ясність, особливо там, де призначення набору команд є незрозумілим. Коментар може містити будь-які друковані символи, включаючи пробіл. Коментар може займати весь рядок або слідувати за командою на тому ж рядку.

Структура програми на асемблері

Програма, написана мовою асемблера, може складатися з кількох частин, які називаються модулями . У кожному модулі можуть бути визначені один або кілька сегментів даних, стека та коду. Будь-яка закінчена програма на асемблері повинна включати один головний, або основний модуль, з якого починається її виконання. Модуль може містити сегменти коду, сегменти даних та стека, оголошені за допомогою відповідних директив. Перед оголошенням сегментів потрібно вказати модель пам'яті за допомогою директиви. MODEL.

Приклад програми, яка нічого не робить, мовою асемблера:

686P
.MODEL FLAT, STDCALL
.DATA
.CODE
START:

RET
END START

У цій програмі представлена ​​лише одна команда мікропроцесора. Ця команда RET. Вона забезпечує правильне закінчення роботи програми. У загальному випадку, ця команда використовується для виходу з процедури.
Решта програми належить до роботи транслятора.
.686P - дозволено команди захищеного режиму Pentium 6 (Pentium II). Ця директива вибирає підтримуваний набір команд асемблера, вказуючи модель процесора. Літера P, зазначена в кінці директиви, повідомляє транслятор про роботу процесора в захищеному режимі.
.MODEL FLAT, stdcall - Плоска модель пам'яті. Ця модель пам'яті використовується в операційній системі Windows. stdcall
.DATA - сегмент програми, що містить дані.
.CODE - блок програми, що містить код.
START – мітка. В асемблері мітки відіграють велику роль, що не скажеш про сучасні мови високого рівня.
END START — кінець програми та повідомлення транслятору, що розпочинати виконання програми треба з мітки START .
Кожен модуль повинен містити директиву END, що позначає кінець вихідного кодупрограми. Усі рядки, які йдуть за директивою END, ігноруються. Якщо опустити директиву END, то генерується помилка.
Мітка, вказана після директиви END повідомляє транслятору ім'я головного модуля, з якого починається виконання програми. Якщо програма містить один модуль, мітку після директиви END можна не вказувати.

Структура команди мовою асемблера Програмування лише на рівні машинних команд - це мінімальний рівень, у якому можливе програмування комп'ютера. Система машинних команд повинна бути достатньою для того, щоб реалізувати необхідні дії, надаючи вказівки апаратурі машини. Кожна машинна команда складається з двох частин: операційної, що визначає "що робити" і операндної, що визначає об'єкти обробки, тобто "над чим робити". Машинна команда мікропроцесора, записана мовою Асемблера, є одним рядком, що має наступний вигляд: мітка команда/директива операнд(и) ; коментарі Мітка, команда/директива та операнд поділяються принаймні одним символом пробілу або табуляції. Операнди команди розділяються комами.

Структура команди мовою асемблера Команда асемблера вказує транслятору, яку дію має виконати мікропроцесор. Директиви асемблера - параметри, задані у тексті програми, які впливають процес асемблирования чи властивості вихідного файла. Операнд визначає початкове значення даних (у сегменті даних) або елементи, над якими виконується дія за командою (сегмент коду). Команда може мати один або два операнди, або не мати операндів. Число операндів неявно задається кодом команди. Якщо команду або директиву необхідно продовжити на наступному рядку, використовується символ «зворотний сліш»: «» . За замовчуванням Асемблер не розрізняє великі та малі літери в написанні команд і директив. Приклади директиви та команди Count db 1; Ім'я, директива, один операнд mov eax, 0; Команда, два операнди

Ідентифікатори – послідовності допустимих символів, які використовуються для позначення імен змінних та назв міток. Ідентифікатор може складатися з одного або кількох таких символів: всі літери латинського алфавіту; цифри від 0 до 9; спецсимволи: _, @, $, ? . Як перший символ мітки може використовуватися точка. Як ідентифікатори не можна використовувати зарезервовані імена асемблера (директиви, оператори, імена команд). Першим символом ідентифікатора має бути буква чи спецсимвол. Максимальна довжина ідентифікатора 255 символів, але транслятор сприймає перші 32, інші ігнорує. Усі мітки, які записуються в рядку, що не містить директиви асемблера, повинні закінчуватися двокрапкою «:». Мітка, команда (директива) та операнд не обов'язково повинні починатися з певної позиції в рядку. Рекомендується записувати їх у стовпчик для більшої дочитальності програми.

Мітки Усі мітки, які записуються в рядку, що не містить директиви асемблера, повинні закінчуватися двокрапкою «:». Мітка, команда (директива) та операнд не обов'язково повинні починатися з певної позиції в рядку. Рекомендується записувати їх у стовпчик для більшої дочитальності програми.

Коментарі Використання коментарів у програмі покращує її ясність, особливо там, де призначення набору команд є незрозумілим. Коментарі починаються на будь-якому рядку вихідного модуля із символу "точка з комою" (;). Усі символи, що знаходяться праворуч від “; » до кінця рядка є коментарем. Коментар може містити будь-які друковані символи, включаючи пробіл . Коментар може займати весь рядок або слідувати за командою на тому ж рядку.

Структура програми мовою асемблера Програма, написана мовою асемблера, може складатися з кількох частин, званих модулями, у кожному з яких можна визначити один чи кілька сегментів даних, стека і коду. Будь-яка закінчена програма мовою асемблері повинна включати один головний, або основний модуль, з якого починається її виконання. Модуль може містити програмні сегменти, сегменти даних та стека, оголошені за допомогою відповідних директив.

Моделі пам'яті Перед оголошенням сегментів необхідно вказати модель пам'яті за допомогою директиви. MODEL модифікатор модель_пам'яті, угода_про_дзвінки, тип_ОС, параметр_стека Основні моделі пам'яті мови асемблера: Модель пам'яті Адресація коду Адресація даних Операційна системаЧергування коду та даних TINY NEAR MS-DOS Допустимо SMALL NEAR MS-DOS, Windows Немає MEDIUM FAR NEAR MS-DOS, Windows Немає COMPACT NEAR FAR MS-DOS, Windows Немає LARGE FAR MS-DOS, Windows Ні Windows Немає NEAR Windows 2000, Windows XP, Windows Допустимо FLAT NEAR NT,

Моделі пам'яті Модель tiny працює тільки в 16-розрядних додатках MS-DOS. У цій моделі всі дані та код розташовуються в одному фізичному сегменті. Розмір програмного файлу у разі не перевищує 64 Кбайт. Модель small підтримує один сегмент коду та один сегмент даних. Дані та код при використанні цієї моделі адресуються як near (ближні). Модель medium підтримує декілька сегментів програмного коду і один сегмент даних, причому всі посилання в сегментах програмного коду за умовчанням вважаються далекими (far), а посилання в сегменті даних - ближніми (near). Модель compact підтримує декілька сегментів даних, у яких використовується дальня адресація даних (far), та один сегмент коду з ближньою адресацією (near). Модель large підтримує декілька сегментів коду та декілька сегментів даних. За замовчуванням усі посилання на код та дані вважаються далекими (far). Модель huge практично еквівалентна моделі пам'яті large.

Моделі пам'яті Модель flat передбачає несегментовану конфігурацію програми і використовується лише в 32-розрядних операційних системах. Ця модель подібна до моделі tiny в тому сенсі, що дані і код розміщені в одному сегменті, тільки 32-розрядному. Для розробки програми моделі flat перед директивою. model flat слід розмістити одну з директив: . 386, . 486, . 586 або. 686. Вибір директиви вибору процесора визначає набір команд, доступних під час написання програм. Літера p після директиви вибору процесора означає захищений режим роботи. Адресація даних та коду є ближньою (near), при цьому всі адреси та покажчики є 32-розрядними.

Моделі пам'яті. MODEL модифікатор модель_пам'яті, угода про виклики, тип_ОС, параметр_стека Параметр модифікатор використовується для визначення типів сегментів і може приймати значення: use 16 (сегменти вибраної моделі використовуються як 16-бітні) use 32 (сегменти обраної моделі використовуються як 32-бітові). Параметр угода_про_дзвінки використовується для визначення способу передачі параметрів при виклику процедури з інших мов, у тому числі і мов високого рівня (C++, Pascal). Параметр може приймати такі значення: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Моделі пам'яті. MODEL модифікатор модель_пам'яті, угода_про_дзвінки, тип_ОС, параметр_стека Параметр тип_ОС дорівнює OS_DOS за замовчуванням, і на Наразіце єдине значення цього параметра, що підтримується. Параметр параметр_стека встановлюється рівним: NEARSTACK (реєстр SS дорівнює DS, області даних і стека розміщуються в тому самому фізичному сегменті) FARSTACK (реєстр SS не дорівнює DS, області даних і стека розміщуються в різних фізичних сегментах). За промовчанням приймається значення NEARSTACK.

Приклад програми, що «нічого не робить». 686 P. MODEL FLAT, STDCALL. DATA. CODE START: RET END START RET – команда мікропроцесора. Вона забезпечує правильне закінчення роботи програми. Решта програми належить до роботи транслятора. . 686 P - дозволено команди захищеного режиму Pentium 6 (Pentium II). Ця директива вибирає підтримуваний набір команд асемблера, вказуючи модель процесора. . MODEL FLAT, stdcall – плоска модель пам'яті. Ця модель пам'яті використовується в операційній системі Windows. stdcall - угода про виклики процедур, що використовується.

Приклад програми, що «нічого не робить». 686 P. MODEL FLAT, STDCALL. DATA. CODE START: RET END START . DATA – сегмент програми, що містить дані. Ця програма не використовує стек, тому сегмент. STACK відсутня. . CODE – сегмент програми, що містить код. START – мітка. END START - кінець програми та повідомлення компілятору, що починати виконання програми треба з мітки START. Кожна програма повинна містити директиву END, яка позначає кінець вихідного коду програми. Усі рядки, які йдуть за директивою END, ігноруються Мітка, вказана після директиви END, повідомляє транслятор ім'я головного модуля, з якого починається виконання програми. Якщо програма містить один модуль, мітку після директиви END можна не вказувати.

Транслятори мови асемблера Транслятор - програма або технічний засіб, що виконує перетворення програми, представленої однією з мов програмування, в програму цільовою мовою, звану об'єктним кодом. Крім підтримки мнемонік машинних команд, кожен транслятор має власний набір директив і макрозасобів, часто ні з чим не сумісних. Основні види трансляторів мови асемблера: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - багатопрохідний асемблер, що вільно розповсюджується, написаний Томашем Гриштаром (польськ.), NASM (Netwide Assembler) - вільний 86, був створений Саймон Тетхем спільно з Юліаном Холл і в даний час розвивається невеликою командою розробників на Source. Forge. net.

Src="https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt="Трансляція програми в Microsoft Visual Studio 2005 1) Створити проект, вибравши меню File->New->Project і"> Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и указав имя проекта (hello. prj) и тип проекта: Win 32 Project. В дополнительных опциях мастера проекта указать “Empty Project”.!}

Src="https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt="Трансляція програми в Microsoft Visual Studio 2005 2) У дереві проекту (View->Solution Explorer) додати"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.!}

Трансляція програми Microsoft Visual Studio 2005 3) Вибрати тип файлу Code C++, але вказати ім'я з розширенням. asm:

Трансляція програми Microsoft Visual Studio 2005 5) Встановити параметри компілятора. Вибрати правою кнопкою у файлі проекту меню Custom Build Rules…

Трансляція програми в Microsoft Visual Studio 2005 і у вікні вибрати Microsoft Macro Assembler.

Трансляція програми в Microsoft Visual Studio 2005 Перевірити правою кнопкою у файлі hello. asm дерева проекту меню Properties і встановити General->Tool: Microsoft Macro Assembler.

Src="https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt="Трансляція програми в Microsoft Visual Studio 2005 6) Відкомпілювати файл, вибравши Build->Build hello. prj."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.!}

Програмування в ОС Windows Програмування в OC Windows ґрунтується на використанні функцій API (Application Program Interface, тобто інтерфейс програмної програми). Їхня кількість досягає 2000. Програма для Windows значною мірою складається з таких викликів. Вся взаємодія з зовнішніми пристроямита ресурсами операційної системи відбувається, як правило, за допомогою таких функцій. Операційна система Windowsвикористовує пласку модель пам'яті. Адреса будь-якого осередку пам'яті визначатиметься вмістом одного 32-бітного регістру. Можливі 3 типи структур програм для Windows: діалогова (основне вікно - діалогове), консольна або безвіконна структура, класична структура (віконна, каркасна).

Виклик функцій Windows API У файлі допомоги будь-яка функція API представлена ​​у вигляді тип ім'я_функції (ФА 1, ФА 2, ФА 3) Тип – тип значення, що повертається; ФАх – перелік формальних аргументів у порядку їхнього прямування Наприклад, int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Ця функціявиводить на екран вікно з повідомленням та кнопкою (або кнопками) виходу. Сенс параметрів: h. Wnd -дескриптор вікна, у якому з'являтиметься вікно-повідомлення, lp. Text - текст, який з'являтиметься у вікні, lp. Caption - текст у заголовку вікна, u. Type – тип вікна, зокрема можна визначити кількість кнопок виходу.

Виклик функцій Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Практично всі параметри API-функцій насправді 32-бітові цілі числа: HWND - 32-бітне ціле, LPCTSTR - 32-бітний покажчик на рядок, UINT - 32-бітне ціле. До імені функцій часто додається суфікс "А" для переходу до нових версій функцій.

Виклик функцій Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); При використанні MASM необхідно наприкінці імені додати @N N – кількість байт, що займають у стеку передані аргументи. Для функцій Win 32 API це число можна визначити кількість аргументів n, помножене на 4 (байта у кожному аргументі): N=4*n. Для виклику функції використовується команда CALL асемблера. При цьому всі аргументи функції передаються до неї через стек (команда PUSH). Напрямок передачі аргументів: ЗЛІВА НАПРАВО - ЗНИЗУ Вгору. Першим поміщатиметься у стек аргумент u. Тип. Виклик цієї функції буде виглядати так: CALL Message. Box. [email protected]

Виклик функцій Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Результат виконання будь-якої функції API - це, як правило, ціле число, яке повертається в регістрі EAX. Директива OFFSET є «зміщення в сегменті», або, переводячи в поняття мов високого рівня, «покажчик» початку рядка. Директива EQU подібно до #define у ​​мові СІ визначає константу. Директива EXTERN вказує транслятору, що функція або ідентифікатор є зовнішнім по відношенню до цього модуля.

Приклад програми "Привіт усім!" . 686 P. MODEL FLAT, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "Моя перша програма", 0 STR 2 DB "Привіт усім!", 0 HW DD? EXTERN Message. Box. [email protected]: NEAR. CODE START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Message. Box. [email protected] RET END START

Директива INVOKE Транслятор мови MASM дозволяє спростити виклик функцій з використанням макрозасобу – директиви INVOKE: INVOKE функція, параметр1, параметр2, … При цьому немає необхідності додавати @16 до виклику функції; параметри записуються точно в тому порядку, в якому наведено опис функції. макрозасобами транслятора параметри містяться у стек. Для використання директиви INVOKE необхідно мати опис прототипу функції з використанням директиви PROTO у вигляді: Message. Box. A PROTO: DWORD, : DWORD Якщо у програмі використовується безліч функцій Win 32 API, доцільно скористатися директивою include C: masm 32includeuser 32. inc




Top