Програмування цифрових пристроїв
3. Лекція1. Про асемблера (1 пара)
Цікаво простежити, починаючи з часу появи перших комп'ютерів і закінчуючи сьогоденням, за трансформаціями уявлень про мову асемблера у програмістів.
Колись асемблер був мовою, без знання якої не можна було змусити комп'ютер зробити щось корисне. Поступово ситуація змінювалась. З'являлися зручніші засоби спілкування з комп'ютером. Але, на відміну інших мов, асемблер не вмирав, навіть він міг зробити цього у принципі. Чому? У пошуках відповіді спробуємо зрозуміти, що таке мова асемблера взагалі.
Якщо коротко, то мова асемблера це символічне уявлення машинної мови. Всі процеси в машині на найнижчому апаратному рівні приводяться в дію тільки командами (інструкціями) машинної мови. Звідси зрозуміло, що, незважаючи на загальну назву, мова асемблера для кожного типу комп'ютера своя. Це стосується і зовнішнього вигляду програм, написаних на асемблері, та ідей, відображенням яких ця мова є.
По-справжньому розв'язати проблеми, пов'язані з апаратурою (або навіть, залежать від апаратури як, наприклад, підвищення швидкодії програми), неможливо без знання асемблера.
Програміст або будь-який інший користувач може використовувати будь-які високорівневі засоби, аж до програм побудови віртуальних світів і, можливо, навіть не підозрювати, що насправді комп'ютер виконує не команди мови, якою написана його програма, а їх трансформоване уявлення у формі нудної та похмурої послідовності команд зовсім іншої мови – машинної. А тепер уявімо, що у такого користувача виникла нестандартна проблема або просто щось не склалося. ДоНаприклад, програма повинна працювати з деяким незвичайним пристроєм або виконувати інші дії, що вимагають знання принципів роботи апаратури комп'ютера. І ось тут і починається зовсім інша історія. Яким би розумним не був програміст, якою б гарною не була мова, якою він написав свою чудову програму, без знання асемблера йому не обійтися. І невипадково практично всі компілятори мов високого рівня містять засоби зв'язку своїх модулів з модулями на асемблері або підтримують вихід асемблерний рівень програмування.
Звичайно, час комп'ютерних універсалів уже минув. Як кажуть не можна осягнути неосяжне. Але є щось спільне, свого роду фундамент, на якому будується будь-яка серйозна комп'ютерна освіта. Це знання про принципи роботи комп'ютера, його архітектуру та мову асемблера як відображення та втілення цих знань.
Типовий сучасний комп'ютер (на базі i486 чи Pentium) складається з наступних компонентів (рис. 1).
Мал. 1. Комп'ютер та периферійні пристрої
З малюнка видно, що комп'ютер складається з кількох фізичних пристроїв, кожне з яких підключено одного блоку, званому системним. Якщо міркувати логічно, то ясно, що він відіграє роль деякого пристрою, що координує. Давайте заглянемо всередину системного блоку (не потрібно намагатися проникнути всередину монітора - там немає нічого цікавого, до того ж це небезпечно): відкриваємо корпус і бачимо якісь плати, блоки, проводи. Щоб зрозуміти їхнє функціональне призначення, подивимося на структурну схему типового комп'ютера (рис. 2). Вона не претендує на безумовну точність і має на меті лише показати призначення, взаємозв'язок та типовий склад елементів сучасного персонального комп'ютера.
Мал.2. Структурна схема персонального комп'ютера
Обговоримо схему на рис. 2 у дещо нетрадиційному стилі. Людині властиво, зустрічаючись із чимось новим, шукати якісь асоціації, які можуть допомогти йому пізнати невідоме. Які асоціації викликає комп'ютер? У мене, наприклад, комп'ютер часто асоціюється із самою людиною. Чому?
Комп'ютер має органи сприйняття інформації із зовнішнього світу — це клавіатура, миша, накопичувачі на магнітних дисках. На рис. 2 ці органи розташовані праворуч від системних шин. У комп'ютера є органи, що "перетравлюють" отриману інформацію - це центральний процесор і оперативна пам'ять. І, нарешті, комп'ютер має органи мови, що видають результати переробки. Це також деякі з пристроїв праворуч.
Сучасним комп'ютерам, звісно, далеко до людини. Їх можна порівняти з істотами, що взаємодіють із зовнішнім світом на рівні великого, але обмеженого набору безумовних рефлексів. Цей набір рефлексів утворює систему машинних команд. На якому високому рівні ви спілкувалися з комп'ютером, зрештою все зводиться до нудної і одноманітної послідовності машинних команд. Кожна машинна команда є своєрідним подразником для збудження того чи іншого безумовного рефлексу. Реакція цей подразник завжди однозначна і “зашита” у блоці мікрокоманд як мікропрограми. Ця мікропрограма і реалізує дії реалізації машинної команди, але вже на рівні сигналів, що подаються на ті чи інші логічні схеми комп'ютера, тим самим керуючи різними підсистемами комп'ютера. У цьому полягає так званий принцип мікропрограмного керування.
Продовжуючи аналогію з людиною, зазначимо: для того, щоб комп'ютер правильно харчувався, придумано багато операційних систем,компіляторів сотень мов програмування тощо. буд. Але вони є, власне, лише стравою, у якому за певними правилами доставляється їжа (програми) шлунку (комп'ютеру). Тільки (ось досада!) шлунок комп'ютера любить дієтичну, одноманітну їжу — подавай йому структуровану інформацію, у вигляді строго організованих послідовностей нулів і одиниць, комбінації яких і складають машинну мову.
Таким чином, зовні будучи поліглотом, комп'ютер розуміє лише одну мову — мову машинних команд. Звичайно, для спілкування та роботи з комп'ютером необов'язково знати цю мову, але практично будь-який професійний програміст рано чи пізно стикається з необхідністю його вивчення. На щастя, програмісту не потрібно намагатися осягнути значення різних комбінацій двійкових чисел, оскільки ще в 50-ті роки програмісти почали використовувати для програмування символічний аналог машинної мови, який назвали мовою асемблера. Ця мова точно відбиває всі особливості машинної мови. Саме тому, на відміну від мов високого рівня, мова асемблера для кожного типу комп'ютера своя.
З усього вищесказаного можна дійти невтішного висновку, що, оскільки мова асемблера для комп'ютера “рідний”, те й найефективніша програма може бути написана лише у ньому (за умови, що її пише кваліфікований програміст). Тут є одне маленьке “але”: це дуже трудомісткий процес, що вимагає великої уваги та практичного досвіду. Тому реально на асемблері пишуть переважно програми, які мають забезпечити ефективну роботу з апаратною частиною. Іноді на асемблері пишуться критичні за часом виконання чи витрачання пам'яті ділянки програми. Згодом вони оформляються у вигляді підпрограм та поєднуються з кодом мовою високого рівня.
4. Лекція 2. Програмна модель мікропроцесора (1 пара)
На сучасному комп'ютерному ринку спостерігається велика різноманітність різних типів комп'ютерів. Тому можна припустити виникнення у споживача питання — як оцінити можливості конкретного типу (чи моделі) комп'ютера та його відмінність від комп'ютерів інших типів (моделей). Розгляди цього лише структурної схеми комп'ютера недостатньо, оскільки вона мало чим відрізняється у різних машин: в усіх комп'ютерів є оперативна пам'ять, процесор, зовнішні устрою. Різними є способи, засоби та ресурси, за допомогою яких комп'ютер функціонує як єдиний механізм. Щоб зібрати докупи всі поняття, що характеризують комп'ютер з точки зору його функціональних програмно-керованих властивостей, існує спеціальний термін - архітектура ЕОМ. Вперше поняття архітектура ЕОМ стало згадуватися з появою машин 3-го покоління для їхньої порівняльної оцінки.
До вивчення мови асемблера будь-якого комп'ютера має сенс приступати тільки після з'ясування того, яка частина комп'ютера залишена видимою та доступною для програмування цією мовою. Це так звана програмна модель комп'ютера, частиною якої є програмна модель мікропроцесора, яка містить 32 регістри в тій чи іншій мірі доступних для використання програмістом. Дані регістри можна розділити на великі групи:
- 16 користувальницьких регістрів;
- 16 системних регістрів.
У програмах мовою асемблера регістри використовуються дуже інтенсивно. Більшість регістрів мають певне функціональне призначення.
Користувацькі регістри
Як випливає з назви, користувальницькимирегістри називаються тому, що програміст може використовувати їх при написанні своїх програм. До цих регістрів відносяться (рис. 1):
Мал. 1. Регістри користувача мікропроцесорів i486 і Pentium
Чому багато хто з цих регістрів наведено з похилою роздільною рисою? Ні, це не різні регістри – це частини одного великого 32-розрядного регістру. Їх можна використовувати у програмі як окремі об'єкти. Так зроблено задля забезпечення працездатності програм, написаних молодших 16-разрядных моделей мікропроцесорів фірми Intel, починаючи з i8086. Мікропроцесори i486 і Pentium мають переважно 32-розрядні регістри. Їхня кількість, за винятком сегментних регістрів, така сама, як і у i8086, але розмірність більша, що й відображено в їх позначеннях — вони мають приставкуe (E xtended).
Розберемося докладніше зі складом та призначенням користувальницьких регістрів.
Регістри загального призначення
Перерахуємо регістри, які стосуються групи регістрів загального призначення. Оскільки ці регістри фізично перебувають у мікропроцесорі всередині арифметико-логического устрою (АЛУ), їх ще називають регістрами АЛУ:
Наступні два регістри використовуються для підтримки так званих ланцюжкових операцій, тобто операцій, які проводять послідовну обробку ланцюжків елементів, кожен з яких може мати довжину 32, 16 або 8 біт:
У архітектурі мікропроцесора на програмно-апаратному рівні підтримується така структура даних, якстек. Для роботи зі стеком у системі команд мікропроцесора є спеціальні команди, а програмної моделі мікропроцесора для цього існують спеціальні регістри:
- esp/sp (Stack Pointer register) - регістр покажчикастека. Містить вказівник вершинистека в поточному сегменті стека.
- ebp/bp (Base Pointer register) - регістр покажчика бази кадру стека. Призначений для організації довільного доступу до даних усередині стека.
Не поспішайте лякатися такого жорсткого функціонального призначення регістрів АЛУ. Насправді більшість з них можуть використовуватися при програмуванні для зберігання операндів практично в будь-яких поєднаннях. Але, як ми зазначили, деякі команди використовують фіксовані регістри для виконання своїх дій. Це потрібно обов'язково враховувати. Використання жорсткого закріплення регістрів для деяких команд дозволяє компактніше кодувати їх машинне подання. Знання цих особливостей дозволить вам за необхідності хоча б на кілька байт заощадити пам'ять, яку займає код програми.
Сегментні регістри
У програмній моделі мікропроцесора є шість сегментних регістрів: cs, ss, ds, es, gs, fs. Їх існування обумовлено специфікою організації та використання оперативної пам'яті мікропроцесорами Intel. Вона у тому, що мікропроцесор апаратно підтримує структурну організацію програми як трьох частин, званих сегментами. Відповідно, така організація пам'яті називаєтьсясегментною.