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

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

Короткий опис мов Ассемблера

Всі мови програмування поділяються за рівнями: низька і висока. Будь-який із синтаксичної системи «сімейки» Асемблера відрізняється тим, що поєднує відразу деякі переваги найпоширеніших і найсучасніших мов. З іншими їх споріднює і те, що цілком можна використовувати систему комп'ютера.

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

Коротко про структуру мови

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

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

Для кожної лінійки процесора існує своя При такому розкладі правильним буде будь-який процес, у тому числі перекладений

Мова Асемблера має кілька синтаксисів, які будуть розглянуті у статті.

Плюси мови

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

Драйвера, операційні системи, BIOS, компілятори, інтерпретатори і т. д. – це все програма мовою Асемблера.

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

Мінуси мови

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

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

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

Команди мови

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


Використання директив

Програмування мікроконтролерів мовою (Ассемблер це дозволяє і чудово справляється з функціонуванням) найнижчого рівня найчастіше закінчується успішно. Найкраще використовувати процесори з обмеженим ресурсом. Для 32-розрядної техніки ця мовапідходить чудово. Часто в кодах можна побачити директиви. Що ж це? І навіщо використовується?

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


походження назви

Завдяки чому отримав назву мова - "Ассемблер"? Йдеться про транслятор і компілятор, які і роблять зашифровку даних. З англійської Assembler означає не що інше, як збирач. Програма не була зібрана вручну, використано автоматичну структуру. Більше того, на даний момент вже у користувачів та фахівців стерлася різниця між термінами. Часто Асемблером називають мови програмування, хоча це лише утиліта.

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

Макрозасоби

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

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

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

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

На тему: Семантичний розбір 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:

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

Команди мови Ассемблер (Лекція)

ПЛАН ЛЕКЦІЇ

1. Основні групи операцій.

Pentium.

1. Основні групи операцій

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

Операціїпересилання,

Арифметичні операції,

Логічні операції,

Операції зсуву,

Операції порівняння тестування,

Бітові операції,

Операції управління програмою;

Операції управління процесором.

2. Мнемокоди команд процесора Pentium

При описі команд зазвичай використовуються їх мнемонічні позначення (мнемокоди), які служать завдання команди при програмуванні мовою Асемблера. Для різних версійАссемблера мнемокоды деяких команд можуть відрізнятися. Наприклад, для команди виклику підпрограми використовується мнемокодCALL або JSR (“ Jump to SubRoutine”). Проте мнемокоды більшості команд основних типів мікропроцесорів збігаються чи відрізняються незначно, оскільки є скороченнями відповідних англійських слів, визначальних виконувану операцію. Розглянемо мнемокоди команд, прийняті для процесорів Pentium.

Команди пересилання. Основною командою цієї групи є командаMOV яка забезпечує пересилання даних між двома регістрами або між регістром і осередком пам'яті. У деяких мікропроцесорах реалізується пересилання між двома осередками пам'яті, а також групове пересилання вмісту кількох регістров з пам'яті. Наприклад, мікропроцесори сімейства 68 xxx компанії Motorola виконують командуMOVE , що забезпечує пересилання з одного осередку пам'яті до іншого, і командуMOVEM , яка здійснює запис у пам'ять або завантаження з пам'яті вмісту заданого набору регістрів (до 16 регістрів). КомандаXCHG виробляє взаємний обмін вмістом двох регістрів процесора або регістру та комірки пам'яті.

Команди введення IN та висновку OUT реалізують пересилання даних з регістру процесора у зовнішній пристрій або прийом даних із зовнішнього пристрою регістр. У цих командах визначається номер інтерфейсного пристрою (порту вводу-виводу), через яке проводиться передача даних. Зазначимо, що багато мікропроцесорів не мають спеціальних команд для звернення до зовнішнім пристроям. В цьому випадку введення та виведення даних у системі виконується за допомогою командиMOV , де задається адреса необхідного інтерфейсного пристрою. Таким чином, зовнішній пристрій адресується як осередок пам'яті, а в адресному просторі виділяється певний розділ, в якому розташовуються адреси підключених до системи інтерфейсних пристроїв (портів).

Команди арифметичних операцій. Основними в цій групі є команди додавання, віднімання, множення і поділу, які мають ряд варіантів. Команди складання ADD та віднімання SUB виконують відповідні операції зcодержимих двох регістрів, регістру та осередку пам'яті або з використанням безпосереднього операнда. Команди AD C , SB B виробляють додавання та віднімання з урахуванням значення ознакиC, що встановлюється при формуванні перенесення у процесі виконання попередньої операції З допомогою цих команд реалізується послідовне додавання операндів, число розрядів яких перевищує розрядність процесора. Команда NEG змінює знак операнда, переводячи його на додатковий код.

Операції множення та поділу можуть виконуватися над числами зі знаком (командиI MUL, I DIV ) або беззнака (команди MUL, DIV ). Один з операцій завжди розміщується в регістрі, другий може перебувати в регістрі, осередку пам'яті або бути безпосереднім операндом. Результат операції розміщується у регістрі. При множенні (командиMUL , IMUL ) Виходить результат подвоєної розрядності, для розміщення якого використовується два регістри. При розподілі (командиDIV , IDIV ) як ділимого використовується операнд подвоєної розрядності, що розміщується у двох регістрах, а як результат у два регістри записується приватне та залишок.

Команди логічних операцій . Практично всі мікропроцесори виробляють логічні операції І , АБО, що виключає АБО, які виконуються над однойменними розрядами операндів за допомогою команд AND, OR, X OR . Операції виконуються над вмістом двох регістрів, регістру та осередку пам'яті або з використанням безпосереднього операнда. Команда NOT інвертує значення кожного розряду операнда.

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

Команди порівняння та тестування . Порівняння операндів зазвичай проводиться за допомогою командиCMP , яка виробляє віднімання операндів із встановленням значень ознак N, Z, V, Cу регістрі стану відповідно до отриманого результату. При цьому результат віднімання не зберігається і значення операндів не змінюються. Подальший аналіз отриманих значень ознак дозволяє визначити відносне значення (>,<, =) операндов со знаком или без знака. Использование различных способов адресации позволяет производит сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.

Деякі мікропроцесори виконують команду тестування TST яка є однооперандним варіантом команди порівняння. При виконанні цієї команди встановлюються ознаки N, Zвідповідно до знака і значення (рівно або не дорівнює нулю) адресованого операнда.

Команди бітових операцій . Ці команди роблять установку значення ознакиCу регістрі станів відповідно до значення тестованого бітаbn в адресованому операнді. У деяких мікропроцесорах за результатом тестування біта проводиться установка ознакиZ. Номер тестованого бітаnвизначається або вмістом зазначеного в команді регістру, або безпосереднім операндом.

Команди цієї групи реалізують різні варіанти зміни тестованого біта. BT зберігає значення цього біта незмінним. B T S післятестування встановлює значення bn=1, а команда B T C - значення bn=0.Команда B T C інвертує значення біта bn після тестування.

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

- команди безумовної передачі керування;

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

- команди організації програмних циклів;

- команди переривання;

- команди зміни ознак.

Безумовна передача керування проводиться командоюJMP , яка завантажує в програмний лічильникPCновий вміст, що є адресою наступної команди. Ця адреса або безпосередньо вказується в командіJMP (пряма адресація) або обчислюється як сума поточного вмістуPCта заданого в команді зміщення, яке є числом зі знаком (відносна адресація). Так якPCмістить адресу чергової команди програми, то останній спосіб задає адресу переходу, зміщений щодо чергової адреси на задану кількість байтів. При позитивному зсуві проводиться перехід до наступних команд програми, при негативному зсуві – до попередніх.

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

Команди управління ознаками забезпечують запис - читання вмісту регістру стану, у якому зберігаються ознаки, і навіть зміна значень окремих ознак. Наприклад, у процесорах Pentium реалізуються команди LAHF і SAHF , які виконують завантаження молодшого байта, де містяться ознаки, з регістру стану EFLAGу молодший байт регістру EAXта заповнення молодшого байта EFLAGSз регістру E AX.. Команди CLC, STCздійснюють встановлення значень ознаки перенесення CF=0, CF=1, а команда CMCвикликає інвертування значення цієї ознаки.Так як ознаки визначають хід виконання програми при умовних переходах, команди зміни ознак зазвичай використовуються для управління програмою.

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

Спеціальні команди CLI, STI забороняють та дозволяють обслуговування запитів переривання. У процесорах Pentium для цього використовується біт управління (прапор)IFу регістрі EFLAGS.

Багато сучасних мікропроцесорів виконують команду ідентифікації, яка дозволяє користувачеві або іншим пристроям отримати інформацію про тип процесора, який використовується в даній системі. У процесорах Pentuimдля цього служить команда CPUID , при виконанні якої необхідні дані про процесор надходять до регістру EAX,EBX ,ECX,EDXі потім можуть зчитуватися користувачем або операційною системою.

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

Деякі процесори роблять арифметичні операції з двійково-десятковими числами або виконують спеціальні команди корекції результату при обробці таких чисел. До складу багатьох високопродуктивних процесорів входить FPU - блок обробки чисел c "плаваючою точкою".

У ряді сучасних процесорів реалізовано групову обробку кількох цілих чисел чи чисел c "плаваючою точкою" за допомогою однієї команди за принципом SIMD (“Single Instruction – Multiple Data ”) - «Одна команда – Безліч даних». Одночасне виконання операцій над кількома операндами суттєво підвищує продуктивність процесора під час роботи з відео- та аудіоданими. Такі операції широко використовуються для обробки зображень, звукових сигналів та інших програм. Для виконання цих операцій до складу процесорів введені спеціальні блоки, що реалізують відповідні набори команд, які у різних типах процесорів ( Pentium Athlon) отримали назвуMMX (“ Milti- Media Extension ”) – Мультимедійне Розширення,SSE(“ Streaming SIMD Extension ”) – Потокове SIMD - Розширення, “3 DExtension- Тривимірне розширення.

Характерною особливістю процесорів компанії Intel , починаючи з моделі 80286, є пріоритетний контроль при зверненні до пам'яті, який забезпечується під час роботи процесора як захищених віртуальних адрес – – “ Protected Mode ” (захищений режим). Для реалізації цього режиму використовують спеціальні групи команд, які служать для організації захисту пам'яті відповідно до прийнятого алгоритму пріоритетного звернення.

Структури в мові асемблер

Розглянуті нами вище масиви є сукупністю однотипних елементів. Але часто у додатках виникає потреба розглядати деяку сукупність даних різного типу як певний єдиний тип.

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

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

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

За визначенням структура - Це тип даних, що складається з фіксованого числа елементів різного типу.

Для використання структур у програмі необхідно виконати три дії:

    Задати шаблон структури .

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

    Визначити екземпляр структури .

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

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

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

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

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

Визначити структуру - отже, дати вказівку транслятору виділити пам'ять і надати цій області пам'яті символічне ім'я.

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

Опис шаблону структури

Опис шаблону структури має наступний синтаксис:

имя_структуры STRUC

ім'я_структури ENDS

Тут є послідовністю директив опису даних db, dw, dd, dqі dt.

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

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

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

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

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

Визначимо структуру запису цієї бази даних наступним шаблоном:

Визначення даних із типом структури

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

[ім'я змінної] ім'я_структури

    ім'я змінної- Ідентифікатор змінної даного структурного типу.

    Завдання імені змінної необов'язково. Якщо його не вказати, буде виділено область пам'яті розміром у суму довжин всіх елементів структури.

    список значень- укладений у кутові дужки список початкових значень елементів структури, розділених комами.

    Його завдання також необов'язкове.

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

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

    Наприклад: victor worker.

Наприклад визначимо кілька змінних із типом описаної вище структури.

Методи роботи із структурою

Ідея введення структурного типу у будь-яку мову програмування полягає у поєднанні різнотипних змінних в один об'єкт.

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

    адресний_вираз- ідентифікатор змінної деякого структурного типу або вираз у дужках відповідно до наведених нижче синтаксичними правилами (рис. 1);

    ім'я_поля_структури- Ім'я поля із шаблону структури.

    Це, насправді, теж адреса, а точніше, усунення поля від початку структури.

Таким чином оператор " . (точка) обчислює вираз

Рис. 5. Синтаксис адресного виразу оператора звернення до поля структури

Продемонструємо на прикладі певної структури worker деякі прийоми роботи із структурами.

Наприклад, витягти в axзначення поля із віком. Оскільки навряд чи вік працездатної людини буде більшим за величину 99 років, то після приміщення вмісту цього символьного поля в регістр axйого буде зручно перетворити на двійкове представлення командою aad.

Будьте уважні, оскільки через принцип зберігання даних "молодший байт за молодшою ​​адресою"старша цифра віку буде поміщена в al, а молодша - у ah.

Для коригування достатньо використати команду xchg al, ah:

mov ax,word ptr sotr1.age; в al вік sotr1

а можна і так:

Подальша робота з масивом структур проводиться так само, як і з одновимірним масивом. Тут виникає кілька запитань:

Як бути з розміром та як організувати індексацію елементів масиву?

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

Після того як став відомий розмір екземпляра структури, організувати індексацію в масиві структур не становить особливої ​​складності.

Наприклад:

Як копіювати поле з однієї структури у відповідне поле іншої структури? Або як зробити копіювання всієї структури? Давайте виконаємо копіювання поля namтретього співробітника у полі namп'ятого співробітника:

mas_sotr worker 10 dup ()

mov bx,offset mas_sotr

mov si, (type worker) * 2; si = 77 * 2

mov di,(type worker)*4 ;si=77*4

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

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

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

Курсова робота

З дисципліни «Системне програмування»

Тема №4: «Рішення задач на процедури»

Варіант 2

СХІДНО-СИБІРСЬКИЙ ДЕРЖАВНИЙ УНІВЕРСИТЕТ

ТЕХНОЛОГІЙ І УПРАВЛІННЯ

____________________________________________________________________

ТЕХНОЛОГІЧНИЙ КОЛЕДЖ

ЗАВДАННЯ

на курсову роботу

Дисципліна:
Тема: Вирішення задач на процедури
Виконавець(и):Главінська Аріна Олександрівна
Керівник: Дамбаєва Сесегма Вікторівна
Короткий зміст роботи: вивчення підпрограм мовою Асемблера,
розв'язання задач з використанням підпрограм
1. Теоретична частина: Основні відомості про мову Асемблер (набір
команд і т.д.), Організація підпрограм, Способи передачі параметрів
у підпрограмах
2. Практична частина: Розробити дві підпрограми, одна з яких перетворює будь-яку задану літеру в заголовну (у тому числі для російських літер), а інша перетворює літеру в рядкову.
перетворює будь-яку задану букву на головну, а інша перетворює букву на рядкову.
перетворює букву на рядкову.
Терміни виконання проекту за графіком:
1. Теоретична частина – 30 % до 7 тижня.
2. Практична частина – 70 % до 11 тижня.
3. Захист – 100% до 14 тижня.
Вимоги до оформлення:
1. Розрахунково-пояснювальна записка курсового проекту має бути представлена ​​в
електронної та твердої копії.
2. Обсяг звіту повинен бути не менше 20 машинописних сторінок без урахування додатків.
3. РПЗ оформляється за ГОСТом 7.32-91 та підписується у керівника.

Керівник роботи __________________

Виконавець __________________

Дата видачі " 26 " вересня 2017 р.


Вступ. 2

1.1 Основні відомості про мову Асемблер. 3

1.1.1 Набір команд. 4

1.2 Організація підпрограм у мові Ассемблер. 4

1.3 Способи передачі параметрів підпрограмах. 6

1.3.1 Передача параметрів через регістри.

1.3.2 Передача параметрів через стек. 7

2 ПРАКТИЧНИЙ РОЗДІЛ 9

2.1 Постановка задачі. 9

2.2 Опис розв'язання задачі. 9

2.3 Тестування програми.

Висновок. 8

Список літератури.


Вступ

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

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

Друга сфера застосування Асемблера пов'язана з оптимізацією виконання програм. Дуже часто програми-перекладачі (компілятори) з мов високого рівня дають дуже неефективну програму машинною мовою. Зазвичай це стосується програм обчислювального характеру, у яких більшу частину часу виконується дуже невелика (близько 3-5%) ділянка програми (головний цикл). Для вирішення цієї проблеми можуть використовуватися так звані багатомовні системи програмування, які дозволяють записувати частини програми різними мовами. Зазвичай основну частину програми записується мовою програмування високого рівня (Фортране, Паскале, З повагою та ін.), а критичні за часом виконання ділянки програми – на Асемблері. Швидкість роботи всієї програми може значно збільшитися. Часто це єдиний спосіб змусити програму дати результат за прийнятний час.

Метою даної курсової є отримання практичних навичок роботи програмування мовою асемблера.

Завдання роботи:

1. Вивчити основні відомості про мову Ассемблер (структура та компоненти програми на Ассемблері, формат команд, організація підпрограм та ін.);

2. Вивчити види бітових операцій, формат та логіку роботи логічних команд Асемблера;

3. Вирішити індивідуальне завдання застосування підпрограм в Асемблері;

4.. Сформулювати висновок про виконану роботу.

1 ТЕОРЕТИЧНИЙ РОЗДІЛ

Основні відомості про мову Ассемблер

Assembler - мова програмування низького рівня, що є формат запису машинних команд, зручний сприйняття людиною.

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

Директиви асемблера дозволяють включати в програму блоки даних (описані явно або зчитані з файлу); повторити певний фрагмент вказану кількість разів; компілювати фрагмент за умовою; задавати адресу виконання фрагмента, змінювати значення міток у процесі компіляції; використовувати макровизначення з параметрами та ін.

Гідності й недоліки

· Мінімальна кількість надлишкового коду (використання меншої кількості команд та звернень на згадку). Як наслідок – більша швидкість та менший розмір програми;

· Великі обсяги коду, велика кількість додаткових дрібних завдань;

· погана читабельність коду, труднощі підтримки (налагодження, додавання можливостей);

· Проблема реалізації парадигм програмування та будь-яких інших скільки-небудь складних конвенцій, складність спільної розробки;

· менша кількість доступних бібліотек, їх мала сумісність;

· Безпосередній доступ до апаратури: портів введення-виводу, спеціальним регістрам процесора;

· максимальне «підганяння» для потрібної платформи (використання спеціальних інструкцій, технічних особливостей «заліза»);

· Непереносимість інші платформи (крім двійково сумісних).

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

· Визначення даних (констант та змінних);

· Керування організацією програми в пам'яті та параметрами вихідного файлу;

· Завдання режиму роботи компілятора;

· Різні абстракції (тобто елементи мов високого рівня) - від оформлення процедур та функцій (для спрощення реалізації парадигми процедурного програмування) до умовних конструкцій та циклів (для парадигми структурного програмування);

· Макроси.

Набір команд

Типовими командами мови асемблера є:

· Команди пересилання даних (mov та ін)

· Арифметичні команди (add, sub, imul та ін.)

· Логічні та побітові операції (or, and, xor, shr та ін)

· Команди управління ходом виконання програми (jmp, loop, ret та ін.)

· Команди виклику переривань (іноді відносять до команд управління): int

· Команди введення-виведення в порти (in, out)

Для мікроконтролерів та мікрокомп'ютерів характерні також команди, що виконують перевірку та перехід за умовою, наприклад:

· jne - перейти, якщо не одно;

· jge - перейти, якщо більше або дорівнює.