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

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

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

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

Варіант 2

СХІДНО-Сибірський державний університет

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

____________________________________________________________________

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

ЗАВДАННЯ

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

дисципліна:
Тема: Рішення задач на процедури
Виконавець (і): Главінская Аріна Олександрівна
Керівник: ДамбаеваСесегма Вікторівна
Короткий зміст роботи: вивчення підпрограм на мові Асемблера,
рішення задач з використанням підпрограм
1. Теоретична частина: Основні відомості про мову Асемблер (набір
команд і т.д.), Організація підпрограм, Способи передачі впараметров
в підпрограма
2. Практична частина: Розробити дві підпрограми, одна з яких перетворює будь-яку задану букву в заголовну (в тому числі для російських букв), а інша перетворює букву в малу.
перетворює будь-яку задану букву в заголовну, а інша перетворює букву в малу.
перетворює букву в малу.
Терміни виконання проекту за графіком:
1. Теоретична частина - 30% до 7 тижня.
2. Практична частина - 70% до 11 тижня.
3. Захист - 100% до 14 тижня.
Вимоги до оформлення:
1. Розрахунково-пояснювальна записка курсового проекту повинна бути представлена \u200b\u200bв
електронної та твердої копіях.
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 Передача параметрів через регістри .. 6

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

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

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

2.2 Опис рішення задачі. 9

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

Висновок. 8

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


Вступ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

· Макроси.

набір команд

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

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

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

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

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

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

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

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

· Jne - перейти, якщо не дорівнює;

· Jge - перейти, якщо більше або равнo.

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

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

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

^ Регістри загального призначення
Всі регістри цієї групи дозволяють звертатися до своїх "молодшим" \u200b\u200bчастинам (див. Рис. 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 \u003d 1 |

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

| 100000sw | mod000r / m | --data-- | data, якщо BW \u003d 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 \u003d 1 |

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

| 100000sw | mod111r / m | --data-- | data, якщо sw \u003d 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 \u003d Zero / Jump if ECX \u003d Zero)

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

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

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

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

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

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

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

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

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

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

Загальні відомості про мову асемблера

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

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

Символічні імена, що вводяться при програмуванні на мові асемблера, як правило відображають семантику програми, а абревіатура команд - їх основну функцію. Наприклад: PARAM - параметр, TABLE - таблиця, MASK - маска, ADD - додавання, SUB - віднімання і т.д. п. Такі імена легко запам'ятовуються програмістом.

Для програмування на мові асемблера необхідно мати складні інструментальні засоби, ніж при програмуванні на машинному мовою: потрібні обчислювальні комплекси на базі мікро - ЕОМ або ПЕОМ з комплектом периферійних пристроїв (алфавітно-цифрова клавіатура, символьний дисплей, НГМД і друкарка), а також резидентні або крос-системи програмування для необхідних типів мікропроцесорів. Мова асемблера дозволяє ефективно писати і налагоджувати значно складніші програми, ніж машинний мову (до 1 - 4 Кбайт).

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

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

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

За допомогою мови асемблера програміст може задати наступні параметри:

мнемоніку (символічне ім'я) кожної команди машинної мови мікропроцесора;

стандартний формат для рядків програми, описуваної на асемблері;

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

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

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

На мові асемблера програма записується порядково, т. Е. Для кожної команди відводиться один рядок.

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

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

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

· Операційної - визначальною, "що робити";

· Операндной - визначальною об'єкти обробки, "з чим робити".

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

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

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

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

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

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

пряма адресація: Ефективний адреса визначається безпосередньо полем зміщення машинної команди, яке може мати розмір 8, 16 або 32 біта.

mov eax, sum; eax \u003d sum

Асемблер заміняє sum на відповідну адресу, що зберігається в сегменті даних (за замовчуванням адресується регістром ds) і значення, що зберігається за адресою sum, поміщає в регістр eax.

непряма адресаціяв свою чергу має такі види:

· Непряма базова (реєстрова) адресація;

· Непряма базова (реєстрова) адресація зі зміщенням;

· Непряма індексна адресація;

· Непряма базова індексна адресація.

Непряма базова (реєстрова) адресація.При такій адресації ефективний адреса операнда може перебувати в будь-якому з регістрів загального призначення, крім sp / esp і bp / ebp (це специфічні регістри для роботи з сегментом стека). Синтаксично в команді цей режим адресації виражається висновком імені регістра в квадратні дужки.

mov eax,; eax \u003d * esi; * Esi значення за адресою esi

Тема 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 Система команд процесора

Система команд процесора представлена \u200b\u200bна малюнку 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 типи пропозицій асемблера.

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

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

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

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

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

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

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

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

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

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

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

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

Поділитися