Рефетека.ру / Информатика и програм-ие

Учебное пособие: Мова програмування Assembler

Лекція 1 Вступна лекція


Загальний огляд дисципліни

Основні аспекти створення системних програм

Типи мов програмування: інтерпретатори, транслятори, компілятори та компоновщики

Моделі пам’яті та компонування програм


1. Загальний огляд дисципліни


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

Отже, сформулюємо чітке визначення курсу:

Системне програмування – дисципліна, яка вивчає засоби та функції операційної системи, пов’язані з керуванням нею, периферійними пристроями та обміну даними між ними.

Історично склалось так, що існують дві мови, які використовуються для роботи на рівні операційної системи – асемблер та С. Перша мова бере свій початок від найпершого компілятора – Автокоду (1952), розробленого Аліком Гленні для комп'ютера Манчестер Марко I. Цей компілятор вперше використовував мнемонічне (у вигляді команд та відповідних операндів) позначення основних операцій, які здатна виконувати машина, які потім перетворювались на коди, зрозумілі машині. Цей процес був названий трансляцією. А мови, похідні від Автокоду, були названі асемблерами (від слова assembly – "збирати", адже програми збирались з окремих "цеглинок", мнемонічних команд). Ці мови працювали фактично на найнижчому рівні, на рівні процесора та його функцій, а пізніше – на рівні функцій операційної системи.

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


2. Основні аспекти створення системних програм


Перед тим, як ввести поняття системної програми, розглянемо спрощену архітектуру комп’ютерної системи:


Мова програмування Assembler

На рівні мікрокоду як правило, працюють прошиті в мікросхемі програми, наприклад, MMX (MultiMedia Extended Set) чи SSE (Sequenced and Structured Extensions/Поширення для роботи з послідовностями та структурами), які фактично є програмами, зашитими в процесор. Ними системне програмування майже не займається, хоч може використовувати їх ресурси, чи викликати такі програми.

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

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

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

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


3. Типи мов програмування: інтерпретатори, транслятори, компілятори та компоновщики


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

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


Мова програмування Assembler


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

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


Мова програмування Assembler


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

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


Мова програмування Assembler


Як видно, ніяких проміжних програм при цьому немає, тобто програма безпосередньо працює з системою, а відтак – швидше.


4. Моделі пам’яті та загальна структура програм


Кожна системна програма обов'язково повинна відповідати певному типу пам'яті. Цим визначається, яким чином ця програма завантажуватиметься в пам'ять, які на неї накладатимуться обмеження, та які ресурси їй доступні. Ці моделі пам'яті однакові як в асемблері, так і в С, тому доцільніше їх розглянути тут. Програми складаються з сегментів (частин). Кожна з яких може бути не більша за 64 Кб. Сегмент може містити код або дані, відповідно до термінів Фон Неймана. Програма може мати сегментів трьох типів: коду, даних та стеку. Відповідно, існує 6 типів моделей пам’яті, які задають співвідношення та обмеження на ці сегменти:

Tiny (дуже малий). Дані та код знаходяться в один та тільки одному сегменті як у двійковому, так і програмному коді.

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

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

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

Large (великий) – позначає тип пам’яті, де розподіл програмного коду по сегментах відбувається за вибором програміста.

Flat (плоский) – програма взагалі не поділяється на сегменти, але може містити обсяг коду даних, більше за 64 Кбайт. Деякі операційні системи такої моделі пам'яті не підтримують, однак це можна обійти за допомогою драйвера-розширювача (наприклад, dos2gw). Така модель пам’яті використовується для великих програм: Windows, Linux тощо.

Лекція 2 Класифікація мов програмування, основні поняття програмування


Класифікація мов програмування за семантикою, за призначенням, за рівнем використання, за способом компіляції

Поняття "транслятор", "компілятор", "інтерпретатор", "компоновщик"

Загальний алгоритм створення програми


1. Класифікація мов програмування за семантикою, за призначенням, за рівнем використання, за способом компіляції


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

1. За семантикою мови поділяються на імперативні та декларативні. Імперативні мови програмування є детальним викладенням якогось процесу обчислення або дій, які повинен виконати процесор або периферійний пристрій, або ж програмний засіб. Прикладом імперативних мов може слугувати будь-яка сучасна мова програмування, наприклад, C чи Assembler. На відміну від них, декларативні мови передбачають насамперед формулювання мети, тобто кінцевого результату. До декларативних мов належать спеціалізовані мови, такі як Prolog або Occam, але найбільш поширеними мовами цього типу є так звані "оболонки", себто командні інтерпретатори, які існують у кожній сучасній операційній системі, і в яких користувач дає операційній системі виконати певні дії над ресурсом.

2. За призначенням мови поділяються на алгоритмічні, математичні, логічні, функціональні, об’єктно-орієнтовані та спеціалізовані. До алгоритмічних належать всі мови, головним завданням яких є виконання певних задач, які піддаються формалізації. Такі мови містять ключові слова для утворення основних елементів алгоритмів – розгалужень, точок вибору, циклів, функцій тощо та відповідних структур даних. Це знову ж таки С, C++, Pascal, Ada тощо. До математичних мов належать такі мови, головною задачею в яких визнається формалізація та розв'язок математичних рівнянь. Чисто математичною мовою прийнято вважати мову Fortran. Ця мова містить виключно засоби для створення складних математичних виразів, але не містить жодного елементу алгоритму. Однак на сьогодні, більшу популярність набули так звані мішані мови, які також увібрали в собі елементи алгоритмічних мов, зберігаючи засоби для відображення математичної нотації. До таких мов належить, зокрема, MathLab. Логічні мови сконцентровані на відображенні логічних тверджень та автоматичному доказі висновків з цих тверджень. Прикладом такої мови може слугувати Prolog, створений для автоматичного доведення теорем. Функціональні мови призначені для моделювання процесів, і хоч вони містять елементи алгоритмічних мов, але їх основною задачею все-таки є процеси фактично без звертання до даних. Прикладом такої мови є Haskell - університетська розробка. Об'єктно-орієнтовані є протилежними за архітектурою. Подібно до концентрації функціональних мов на функціях та процесах, ці мови концентруються на маніпуляції даними та відносинами між ними, до яких прив'язуються відповідні дії. Класичними об'єктно-орієнтованими мовами є SmallTalk та C++. Спеціалізовані мови можуть містити будь-які конструкції та засоби, відповідно до специфіки сфери, для яких їх призначено. Так, мови розмітки документів XML та HTML містять способи вказання способу відображення даних у Web-браузері, а мова APL – методи для обробки векторних даних.

3. За рівнем використання мови поділяються на низькорівневі, високорівневі, надвисокорівневі та мішані. Низькорівневі мови працюють на рівні операційної системи та команд процесора. Найчастіше це асемблери різних типів. Високорівневі мови – на рівні так званого інтерфейсу програміста, написаного на низькорівневих мовах для забезпечення виконання певних типових задач, як, наприклад, звертання до файлової системи за допомогою більш універсальних засобів, ніж переривання або функції ОС. До цих мов можна віднести C++, Perl, Ada або Pascal. Надвисокорівневі мови, як правило, розширюють можливості певного комплексного програмного засобу, або ж побудовані на бібліотеках так званих компонентів – готових "цеглинок" для побудови кінцевого продукту. Такі мови (а точніше – діалекти, оскільки чистих мов такого типу на сьогодні не існує) – Object Pascal, Visual C++. Мішаними називають такі мови, які здатні працювати на кількох рівнях у межах однієї програми. Класичною мовою такого типу є C, яка містить засоби роботи як на низькому, так і високому рівнях.

4. За типом компіляції мови поділяються на інтерпретовані, трансльовані та мішані. Інтерпретовані мови, як вже здавалося вище, існують у вигляді відкритого програмного коду, який при виконанні рядок за рядком перетворюється в машинний код проміжною програмою-інтерпретатором. Прикладом такої мови є Rexx, Objective (діалект мови З) та Forth. Трансльовані мови цілком перетворюються в машинний код після аналізу програмного коду. Прикладами таких мов можуть слугувати більшість алгоритмічних мов на сьогодні. Мішаними називаються такі мови, які поєднують у собі кращі риси обох цих типів. Першою такою мовою була створена Sun Microsystems мова Java, яка компілюється в кросплатформений байт-код, а потім інтерпретується віртуальною машиною, яка транслює цей проміжний код у машинний код для поточного процесора. На сьогодні існує ще дві такі мови: C# та Python.


2. Поняття "транслятор", "компілятор", "інтерпретатор", "компоновщик"


Транслятор – програма, яка перетворює програмний код, викладений на певній мові програмування, у машинний код.

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

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

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


3. Загальний алгоритм створення програми


Загальний алгоритм можна звести до простої діаграми:


Мова програмування Assembler

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

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

1. Ім'я вихідного файлу. Якщо при відповіді не зазначене розширення, передбачається ASM.

2. Ім'я об'єктного файлу. Якщо при відповіді не зазначене розширення, передбачається OBJ. Базове ім'я об'єктного файлу за замовчуванням збігається з базовим ім'ям вихідного файлу.

3. Ім'я файлу лістинга. Якщо при відповіді не зазначене розширення, передбачається LST. Базове ім'я файлу лістинга за замовчуванням NUL.

4. Ім'я файлу перехресних посилань. Якщо при відповіді не зазначене розширення, передбачається CRF. Базове ім'я файлу лістинга за замовчуванням NUL.

Наприкінці будь-якої відповіді після символів "/" або - "," можуть бути задані опції макроасемблера.

Якщо в якій-небудь відповіді специфіковано символ ";", MASM вийде з діалогового режиму й встановить імена, що залишилися, за замовчуванням з наступного списку:


<ім'я вихідного файлу>.OBJ

NUL.LST

NUL.CRF


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

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


MASM <ім'я вихідного файлу>[,[<ім'я об'єктного файлу>]

[,[<ім'я файлу лістинга>][,[<ім'я файлу перек. посилань>]]]]

[<опції>][;]


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

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

Опції MASM можуть розташовуватися в будь-якому місці командного рядка.


Лекція 3 Порівняльна характеристика С та асемблера


Визначення низькорівневої мови

Порівняльна характеристика мов Assembler та C

Види асемблерів

Види компіляторів C


1. Визначення низькорівневої мови


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


2. Порівняльна характеристика мов Assembler та C


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

Сі має невеликий набір типів даних: цілі числа, числа з комою, що плаває, бітові поля і перерахований тип. У мові Сі ви можете описати змінну типу покажчик, що зв'язується з об'єктом, який належить до будь-якого типу даних. Адресна арифметика мови Сі є чутливою до типу даних того об'єкта, з яким зв'язаний використовуваний покажчик. Дозволені також покажчики до функцій. Ви можете розширити список типів даних шляхом створення структур з ієрархічною залежністю типів даних, що входять у нього. Кожен тип даних може належати або до основного типу, або до раніше описаного структурного типу. Об'єднання нагадують структури, але визначають різні види ієрархічних залежностей, у яких дані різних типів розташовуються в пам'яті.

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

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

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

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

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

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


3. Види асемблерів


Макроасемблер MASM фірми MICROSOFT асемблює програми мовою асемблера для мікропроцесорів 8086, 8088, 80186 і 80286 і створює об'єктні файли, що можуть редагуватися і виконуватися в операційній системі MS-DOS. Макроасемблер забезпечує виконання наступних функцій:

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

2. Синтаксичний аналіз отриманого тексту і виведення необхідної діагностичної інформації.

3. Формування об'єктного модуля. Сприймаючи як вхід один файл із вихідним текстом, макроасемблер може формувати до трьох вихідних файлів, як показано на рис. 2.1.


Мова програмування Assembler

Рис. 2.1. Робота макроасемблера


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

Файл перехресних посилань містить усі використовувані у вхідному тексті ідентифікатори. Надалі він може бути використаний утилітою CREF.

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


4. Види компіляторів C


Borland International

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

Computer Innovation Inc

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

Datalight Inc

З появою Optimum-C Datalight стала одним з перших постачальників, що запропонували оптимізований компілятор. Хоча набір тестів не підтвердив наочно претензії Datalight на глобальну оптимізацію, Optimum-C спрацював так добре в деяких фрагментах тесту, що продемонстрував слабкі фрагменти набору, які вимагають змін для удосконалення бажаної перевірки. Наприклад, у першій версії функції jump-compression не поверталося значення, що робило всі обчислення і присвоювання у функції зайвими. Optimum-C виявив це і видалив велику частину коду функції, включаючи ланцюжок переходів. У тесті розмноження констант і копій Optimum-C визначив, що присвоювання i5 в обох умовних операторах є зайвим стосовно наступних присвоювань. Компілятор видалив не тільки ці присвоювання, але й умовні оператори. Незадовільним виявилося видалення зайвих збережень значень регістрів. Optimum-C - єдиний компілятор, що намагався виконати глибоке видалення загальних виражень. Перевірка згенерованого коду показала, що загальне вираження i5+i2 було переміщено вище першого базового блоку умовного оператора, але не було вилучено з другого. Поза обмеженнями на стандартне використання регістрів, що накладаються сімейством мікропроцесорів 80x86, Optimum-C розумно використовує регістри. У функції jump-compression кожен переданий параметр був поміщений у регістр. Усередині тіла функції не було посилань у пам'ять, крім початкового засилання в регістри. Однією важливою областю, у якій компілятор Optimum-C вимагає поліпшень, є оптимізація циклів. Компілятор не намагається виконувати винесення інваріантного коду і видалення змінних індукції циклу. Тест виконання показав, що компілятор Datalight дуже ефективно керує введенням/висновком getc/putc, а інші тести виконуються в прийнятний час.

Lattice Inc

Компілятор, що має велику історію, Lattice MS-DOS C послідовно удосконалювався з кожною новою версією. Він відомий як генератор стабільного, передбачуваного коду і виконує помірну оптимізацію. Lattice С виконує зниження потужності, стиск ланцюжка переходів і видалення загальних підвиразів. Він не видаляє присвоювання, що дублюються після тесту вбудованих функцій і зайві присвоювання у функції dead-code. Lattice C не виконує оптимізацію циклів.

Manx Software Systems Inc

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

Metaware Inc

High C виробляє чудовий код із середнім рівнем оптимізації. Компілятор виконує всі базові види оптимізації, включаючи згортку констант і алгебраїчні спрощення, видалення зайвих операцій завантаження регістрів, зниження потужності і видалення загальних підвиразів. Компілятор Metaware видаляє недосяжний код, але не видаляє зайві присвоювання. High C розумно використовує машинно-залежні інструкції. Компілятор удосконалить завантаження констант із крапкою, що плаває, використовуючи команду копіювання рядків MOVS процесорів 80x86 для запису значень із крапкою, що плаває, обчислених під час компіляції. Він також генерує інструкцію LEAVE процесорів 80x86 для епілогу функцій, але встановлює адресацію стекового фрейму в пролозі функції за допомогою окремих інструкцій, а не використовуючи більш тривалу інструкцію ENTER. Компілятор High C не виконує винесення інваріантного коду, важливий метод оптимізації циклів. Він також не зміг застосувати успішне видалення змінних індукції циклів. Вбудовані функції підтримуються для декількох цілочисленних і строкових операцій, таких як strlen.

Microsoft C

У версії 5.0 свого компілятора Сі корпорація Microsoft вивела на ринок PC високий рівень оптимізації коду. Microsoft приділяє багато уваги аналізу циклів. C 5.0 - єдиний з розглянутих компіляторів, що виконує винесення інваріантного коду і сьогоденне видалення змінних індукції циклів. Компілятор Microsoft C 5.0 чудово використовує регістри, намагаючись мінімізувати звертання до пам'яті в тілі циклу . Простий приклад циклу в коді тесту демонструє ступінь оптимізації циклів, який виконує Microsoft C 5.0. Компілятор застосовує зниження потужності і цілком видаляє константне множення, виявляє кінцевий стан змінних, і поміщає в регістри всі змінні всередині циклу. C 5.0 видаляє цикл for і генерує код тільки з метою установки кінцевого стану змінної - індексу циклу й оператора, включеного в цикл. Компілятор також добре використовує регістри. Увага фірми Microsoft до оптимізації винагороджується при роботі тесту виконання. Він виконується за час, що є кращим чи близько до кращого по кожній категорії.

WATCOM

Новітній суперник, що завойовує позиції на ринку компіляторів C - WATCOM C 6.0 (див. Product Watch, Philip N. Hisley, за цей місяць). C 6.0 виробляє компактний код, що чудово використовує трохи обмежений комплект регістрів сімейства 80x86. Крім виконання базових прийомів оптимізації, він підтримує зниження потужності і видалення недосяжного коду і загальних підвиразів. У той час, як Microsoft досягає поліпшення коду завдяки оптимізації циклів, WATCOM збільшує швидкість шляхом зменшення керуючих заголовків викликів функцій до їхнього абсолютно мінімального розміру. Він досягає цього, шляхом переважної передачі параметрів через регістри, а не через стек. WATCOM дуже добре видаляє недосяжний код. C 6.0 не тільки видалив непотрібні присвоювання і недосяжний код усередині функції, але він також видалив пролог і епілог функції і згорнув усю функцію до простого повернення, приписавши ім'я функції до інструкції повернення основної функції. На завершення всього, компілятор видалив локальний виклик функції. Наскільки C 6.0 витончений у знищенні марної функції, настільки ж він безпомічний при видаленні марного присвоювання, що дублюється. Найбільш важлива область, за яку WATCOM C 6.0, як і Optimum-C, не зміг узятися, була оптимізація циклів. Він не підтримує винесення інваріантного коду і видалення змінної індукції циклів. Хоча C 6.0 не виконує розгортання циклів в окремі команди, він (також як Datalight Optimum-C і Computer Innovations C86Plus) використовує команду REP/STOSW процесорів 80x86 для ініціалізації тестового масиву, завдяки чому видаляє цикл. Прекрасна генерація коду в WATCOM, зокрема, розумне використання регістрів, дає йому дуже важлива перевага. Він переміг у більшості тестів, що інтенсивно використовують процесор, і при цьому виконувався для великої моделі в кращий час, ніж більшість інших компіляторів для малої моделі. До слабких сторін WATCOM можна віднести введення/виведення файлів, використання getc і putc. Тут він близький до найгірших компіляторів.


Лекція 4


Поняття "об'єктного файлу" та "виконуваного модуля"

Архітектура виконуваного модуля

Поняття "компонування"

Види заголовків виконуваних файлів та огляд видів форматів виконуваних модулів та об’єктних файлів


1. Поняття "об’єктного файлу" та "виконуваного модуля"


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

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


2. Архітектура виконуючого модуля


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

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

2. Компонує окремо, якщо необхідно, більше одного асемблюваного модуля в одну завантажувальну (здійсненну) програму; можливо дві чи більше асемблерних програм, або асемблерну програму з програмами, написаними на мовах високого рівня, таких як Паскаль чи Бейсік.

3. Ініціалізує EXE-модуль командами завантаження для виконання.

Після компоновки OBJ-модуля (одного чи більше) у EXE-модуль, можна виконати EXE-модуль будь-яку кількість раз. Але, якщо необхідно внести деякі зміни в EXE-модуль, варто скорегувати вихідну програму, асемблювати її в інший OBJ-модуль і виконати компоновку OBJ-модуля в новий EXE-модуль. Навіть, якщо ці кроки поки залишаються незрозумілими, ви зрозумієте, що, одержавши небагато навичок, весь процес підготовки EXE-модуля буде доведений до автоматизму. Помітьте: визначені типи EXE-програм можна перетворити в дуже ефективні COM-програми. Якщо в результаті асемблюваня не виявлено помилок, то cлідуючий крок - компоновка об'єктного модуля. Файл EXASM1.OBJ містить тільки машинний код у шістнадцятковій формі. Оскільки програма може завантажуватися майже в будь-яке місце пам'яті для виконання, тому асемблер може не визначити всі машинні адреси. Крім того, можуть використовуватися інші (під) програми для об'єднання з основними. Призначенням програми LINK є завершення визначення адресних посилань і об'єднання (якщо потрібно) декількох програм. Для виконання можна також створювати COM-файли. Прикладом часто використовуваного COM-файлу є COMMAND.COM. Програма EXE2BIN.COM в оперативній системі DOS перетворить EXE-файли в COM-файли. Фактично ця програма створює BIN (двійковий) файл, тому вона і називається "перетворювач EXE у Вin (EXE-to-BIN)". Вихідний Вin-файл можна переназвати у COM-файл.

РОЗХОДЖЕННЯ МІЖ ПРОГРАМАМИ В EXE і COM-файлах

Незважаючи на те, що EXE2BIN перетворить EXE-файл у COM-файл, існують визначені розходження між програмою, виконуваної як EXE-файл, і програмою, виконуваної як COM-файл.

Розмір програми.

EXE-програма може мати будь-який розмір, у той час як COM-файл обмежений розміром одного сегмента і не перевищує 64ДО. COM-файл завжди менший, ніж відповідаючий EXE-файл; одна з причин цього - відсутність у COM-файлі 512-байтового початкового блоку EXE-файлу.

Сегмент стека.

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

Сегмент даних.

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

Ініціалізація.

EXE-програма записує нульове слово в стек та ініціалізує регістр DS, тому що COM-програма не має ні стека, ні сегмента даних, де ці кроки відсутні. Коли COM-програма починає працювати, усі сегментні регістри містять адресу префікса програмного сегмента (PSP), - 256-байтового (тичина. 100) блоку, що резервується операційною системою DOS безпосередньо перед COM чи EXE програмою в пам'яті. Оскільки адресація починається з точки зсуву 100 від початку PSP, то в програмі після оператора SEGMENT кодується директива ORG 100H.

Обробка.

Для програм у EXE і COM форматах виконується асемблювання для одержання OBJ-файлу, і компоновка для одержання EXE-файлу. Якщо програма створюється для виконання як EXE-файл, то її вже можна виконати. Якщо ж програма створюється для виконання як COM-файл, то компоновщиком буде видане повідомлення:

Warning: No STACK Segment

(Попередження: Сегмент стека не визначено)

Це повідомлення можна ігнорувати, тому що визначення стека у програмі не передбачалося. Для перетворення EXE-файлу у COM-файл використовується програма EXE2BIN. Припустимо, що EXE2BIN мається на дисководі A, а скомпонований файл по імені CALC.EXE - на дисководі B. Уведіть EXE2BIN B:CALC,B:CALC.COM. Оскільки перший операнд завжди припускає EXE файл, то можна не кодувати тип EXE. Другий операнд може мати інше ім'я (CALC.COM). Якщо не вказувати тип COM, то EXE2BIN прийме за замовчуванням тип BIN, який згодом можна перейменувати в COM. Після того як перетворення буде виконано, можна видалити OBJ і EXE-файли. Якщо вихідна програма написана для EXE-формату, то можна, використовуючи редактор, замінити команди у вихідному тексті для COM файлу.

ОСНОВНІ ПОЛОЖЕННЯ НА ПАМ'ЯТЬ

- Обсяг COM-файлу обмежений 64ДО.

- COM-файл менший, ніж відповідний EXE-файл.

- Програма, написана для виконання в COM-форматі не містить стека і сегмента даних і не вимагає ініціалізації регістра DS.

- Програма, написана для виконання в COM-форматі, використовує директиву ORG 100H після директиви SEGMENT для виконання з адреси після префікса програмного сегмента.

- Програма EXE2BIN перетворить EXE-файл у COM-файл, обумовлений указівкою типу COM у другому операнді.

- Операційна система DOS визначає стек для COM-програми або наприкінці програми, якщо дозволяє розмір, або ж наприкінці пам'яті.


3. Поняття "компонування"


Об'єктний лінкер призначений для створення виконавчих файлів з об'єктних файлів, сформованих MASM чи компіляторами C або PASCAL. LINK формує пересувний виконавчий код, позначений інформацією переміщення, використовуючи яку, MS-DOS зможе завантажити в пам'ять і виконати відповідну програму. LINK може формувати програми, що містять понад 1М коду і даних. Сприймаючи на вхід 2 файли, LINK може формувати 2 вихідних файли, як показано на рис.3.1.


Мова програмування Assembler

Рис. 3.1. Робота LINK.


Розширення імен файлів, показані на малюнку, приймаються за замовчуванням. Об'єктний файл містить об'єктні модулі програмних сегментів, сформовані MASM чи компілятором мови високого рівня. Бібліотеки містять набори модулів, на яких можуть посилатися програмні сегменти в об'єктному файлі. Бібліотечні файли формуються за допомо- гою утиліти LIB. Основним результатом роботи LINK є виконавчий файл, що містить програму у виді, придатному для завантаження в пам'ять і виконання. Деякі особливості формування виконавчого файлу описані в п.3.4. Файл плану є необов'язковим і містить, якщо він формується, деяку діагностичну і службову інформацію, яка потім за допомогою утиліти MAPSYM може бути використана в процесі налагодження програми. Файл плану містить імена, завантажувальні адреси і довжини усіх сегментів програми. Крім того, сюди входять імена і завантажувальні адреси груп у програмі, адреса крапки входу, а також повідомлення про можливі помилки.

Якщо задана опція /MAP, у файл включаються імена загальних символів і їхні завантажувальні адреси. Якщо задані опції /HIGH чи /DSALLOCATE і обсяг програми та даних у сукупності не перевищує 64ДО, план може містити символи з незвичайно великими адресами сегментів. Ці адреси відбивають змінні, розташовані нижче дійсного початку сегмента.

Приклад:

FFF0:0A20 TEMP

Адреса TEMP - 00:920h.

Необхідно мати те, через що, крім двох вихідних файлів, LINK може формувати тимчасовий файл з ім'ям VM.TMP. Це відбувається в тому випадку, коли лінкеру не вистачає оперативної пам'яті. Створення файлу VM.TMP супроводжується повідомленням на консолі і завжди здійснюється у поточному підзаголовку. У цьому випадку не можна використовувати опцію /PAUSE і знімати дискету, якщо вона знаходиться на активному драйві, до того, як LINK не знищить файл VM.TMP. Не реко- мендується створювати в поточному підзаголовку файл із таким ім'ям, що у цьому випадку може бути зіпсований.


3. Запуск LINK


Запуск LINK може бути здійснений трьома способами:

1. З використанням підказок.

2. За допомогою командного рядка DOS.

3. З використанням файлу відповіді.

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

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

2. Ім'я виконавчого файлу. Якщо при відповіді не зазначено розширення, передбачається EXE. Базове ім'я виконавчого файлу за замовчуванням збігається з базовим ім'ям об'єктного файлу.

3. Ім'я файлу плану модуля. Якщо при відповіді не зазначене розширення, передбачається MAP. Базове ім'я по умовчанню NUL.

4. Ім'я бібліотеки. Якщо при відповіді не зазначене розширення, передбачається LIB. Можна задавати кілька імен бібліотек за аналогією з OBJ-файлами.Якщо, не вводячи імені, відразу натиснути ENTER,бібліотеки використовуватися не будуть.У кожній відповіді після символу / можуть бути задані опції LINK, що описані в п.3.3. Якщо в якій-небудь відповіді специфікований символ ";", LINK вийде з діалогового режиму й встановить, що залишилися імена за замовчуванням з наступного списку:


<ім'я об'єктного файлу>.EXE

NUL.MAP


Бібліотеки не використовуються.

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


LINK <ім'я об'єктного файлу>[,[<ім'я виконавчого файлу>]

[,[<ім'я файлу плану>][,[<ім'я бібліотеки>]]]][<опції>][;]


Символ ; може бути специфікований у будь-якому місці командного рядка до того, як були визначені усі файли. У цьому випадку імена невизначених файлів, що залишилися, приймаються за замовчуванням із приведеного вище списку. З цього ж списку приймаються за замовчуванням імена файлів, специфікація яких у командному рядку опущена (за допомогою зайвої коми). Якщо в командному рядку виявлена помилка, про це повідомляється через консоль, і LINK переходить у діалоговий режим. Якщо специфікована хоча б одна з опцій /MAP чи /LINENUMBERS, файл плану створюється незалежно від того, чи зазначене його ім'я в командному рядку. У цьому випадку, якщо його ім'я не специфіковане, воно приймається за замовчуванням - <ім'я об'єктного файлу>.MAP. При вказівці декількох об'єктних файлів бібліотек їхні імена розділяються символами + . Якщо визначені не усі файли (але не опущені за допомогою зайвої коми, і не специфікована установка імен, що залишилися, за замовчуванням указівкою символу ";"), LINK входить у діалоговий режим і запитує які залишилися невизначеними імена через підказки.

Специфікації імен файлів і опції можуть бути заздалегідь занесені в спеціальний файл відповіді. Ім'я цього файлу з попереднім символом @ і вказівкою шляху пошуку, якщо він потрібен, може бути поміщене в будь-якому місці відповіді на підказку чи командного рядка і трактується так, аби вміст файлу відповіді був безпосередньо вставлений в це місце. Важливо, однак, пам'ятати, що комбінація символів CARRIAGE-RETURN / LINE-FEED у файлі відповіді інтерпретується як ENTER у підказці чи кома в командному файлі. Загальний вид файлу відповіді:


<ім'я об'єктного файлу>

[<ім'я виконавчого файлу>]

[<ім'я файлу плану>]

[<ім'я бібліотеки>]


Кожна група файлів повинна задаватися на окремому рядку, а файли в групі, якщо їх небагато, повинні розділятися символом +. Якщо група не міститься на одному рядку, в останній позиції рядка повинна стояти ознака продовження - символ +. У будь-якому рядку файла відповіді після символу / можуть бути задані опції LINK. У файлі відповіді можуть бути опущені компоненти, уже визначені відповідями на підказки командним рядком. При виявленні у файлі відповіді символа ; залишок файлу ігноруєть- ся, і невизначені імена, що залишилися установлюються за замовчу- ванням із приведеного вище списку. При використанні файлу відповіді, його вміст видається на консоль у формі підказок. Якщо визначені не усі імена, LINK переходить у діалоговий режим. Якщо файл відповіді не містить комбінації символів CARRIAGE-RETURN / LINE-FEED чи символу ; , LINK видає на консоль останній рядок файлу й очікує натискання ENTER. Ім'я кожного файлу може супроводжуватися інформацією про підрозділ, що містить цей файл, інакше пошук вихідного або файлу створення вихідного файлу, буде здійснюватися в поточному підрозділі. Робота LINK може бути в будь-який момент припинена натисканням клавіш CONTROL-C.

Опції LINK.

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

/HELP (HE) - Видати список діючих опцій. Цю опцію не можна використовувати разом з ім'ям файлу.

/PAUSE (P) - Пауза перед записом модуля в EXE-файл (і після запису в MAP-файл, якщо це передбачено). Під час цієї паузи можна при необхідності переставити дискети. Якщо використовується файл VM.TMP, він повинен знаходитися на тій же дискеті, що і EXE-файл.

/EXEPACK (E) - Установити компактний запис послідовностей однакових біт. Такий EXE-файл має менший обсяг і швидше завантажується в пам'ять, але його не можна налагоджувати за допомогою SYMDEB. Опція дає ефект, якщо програма містить довгі потоки ідентичних бітів і вимагає великого числа (більше 500) переміщень при завантаженні.

/MAP (M) - Формувати MAP-файл. Файл формується, навіть якщо він не специфікований при запуску LINK, і має в цьому випадку ім'я, що умовчується, (п.3.2).

/LINENUMBERS (LI) - Зафіксувати в MAP-файлі номера рядків вихідного файлу. Ця інформація може надалі використовуватися MAPSYM і SYMDEB. Запис номерів рядків буде вироблятися, якщо створюється MAP-файл і об'єктний модуль містить дані про рядки вихідного тексту. Компілятори FORTRAN і PASCAL (версії 3.0 і вище), і C (версії 2.0 і вище) такі дані автоматично формують; у MASM це не передбачено. Якщо MAP-файл не специфіковано, його можна створити примусово, вказавши описувану опцію в підказці на цей файл.

/NOIGNORECASE (NOI) - Установити розходження між рядковими і заголовними буквами. Розходження може бути встановлене також опціями /ML і /MX MASM.

/NODEFAULTLIBRARYSEARCH (NOD) - Ігнорувати, що умовчуються бібліотеки, посилання на яких містяться в об'єктному модулі (їх туди поміщають компілятори мов високого рівня). Використовуються тільки бібліотеки, специфіковані при запуску LINK.

/STACK:<число> (ST) - Установити розмір стека (у байтах). Інформація про розмір стека, що міститься в об'єктному модулі, ігнорується. Розмір стека може бути заданий у виді десяткового, 8-ричного (з попереднім 0) чи 16-ричного (с попередніми 0 і x на малому регістрі) числа в межах від 1 до 65535. Розмір стека може бути змінений утилітою EXEMOD.

/CPARMAXALLOC:<число> - Установити максимальне (C) число 16-байтних параграфів, необхідних при завантаженні програми в пам'ять. Звичайно LINK установлює максимальне число параграфів - 65535. Указівка цієї опції дозволяє більш ефективно використовувати пам'ять. Число параграфів може бути задане у виді десяткового, 8-ричного (з попереднім 0) чи 16-ричного (з попередніми 0 і x на малому регістрі) числа в межах від 1 до 65535. Якщо число параграфів недостатнє для розміщення програми, LINK нарощує його до мінімально придатного. Число параграфів може бути змінене утилітою EXEMOD. Крім розміщення програми, опція може знадобитися для команди ! SYMDEB.

/HIGH (H) - Встановити адреса початку програми на найвищий можливий адрес вільної пам'яті. Без цієї опції установка здійснюється на мінімальну можливу адресу.

/DSALLOCATE (D) - Обробити групу з ім'ям DGROUP. Звичайно LINK привласнює молодшому байту групи зсув 0000h. При завданні цієї опції старшому байту групи з ім'ям DGROUP привласнюється зсув FFFFh. У результаті, дані будуть розміщуватися в областях програми з максимально великими адресами. Опція /D звичайно застосовується разом з опцією /H для більш ефективного використання незайнятої пам'яті до старту програми. LINK припускає, що усі вільні байти в DGROUP займають пам'ять безпосередньо перед програмою. Для використання групи необхідно завантажити в регістр сегмента адреса початку DGROUP.

/NOGROUPASSOCIATION - Ігнорувати групи при (NOG) присвоєнні адрес елементам даних і коду. Опція введена для сумісності з ранніми версіями компіляторів FORTRAN і PASCAL (версії MICROSOFT 3.13 і раніше і IBM до 2.0). Не рекомендується використовувати цю опцію в інших цілях.

/OVERLAYINTERRUPT:<число> - Установити номер переривання при (O) завантаженні оверлейного модуля. Зазначене число заміщає номер стандартного оверлейного переривання (03Fh). Номер може бути заданий у виді десяткового, 8-ричного (з попереднім 0) чи 16-ричного (з попередніми 0 і x на малому регістрі) числа в межах від 0 до 255. MASM не сприяє створенню оверлейних програм. Тому тільки за допомогою опції /O асемблерні модулі можуть бути включені в оверлейні програми на мовах високого рівня, компілятори яких піддержують оверлей. Не рекомендується встановлювати номер, що збігається з яким-небудь іншим перериванням.

/SEGMENTS:<число> (SE) - Установити максимальне число сегментів, що може обробити LINK. Число може бути задане в десяткової, 8-ричній (з попереднім 0) чи 16-ричній (з попередніми 0 і x на малому регістрі) формі в межах від 1 до 1024. При відсутності специфікації опції покладається 128. Пам'ять виділяється з обліком цього максимального числа сегментів.

/DOSSEG (DO) - Упорядкувати сегменти в EXE-файлі. При специфікації цієї опції сегменти розташовуються в наступній послідовності: - сегменти з класом CODE; - інші сегменти, що не входять у групу DGROUP; - сегменти, що входять у DGROUP. Звичайна послідовність сегментів при відсутності /DO описана в п.3.4.3.

Особливості роботи LINK.

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

Вирівнювання сегментів.

Для установки початкової адреси сегмента LINK використовує тип, що задається директивою SEGMENT, вирівнювання: BYTE, WORD, PARA чи PAGE. Ці ключові слова забезпечують вирівнювання початку сегмента відповідно до границі байта, слова (2 байти), параграфа (16 байтів) чи сторінки (256 байтів). За замовчуванням використовується тип PARA. Байти, що пропускаються через вирівнювання, заповнюються війковими нулями.

Номер кадру.

Якщо обчислюється LINK початкова адреса сегмента залежить від типу вирівнювання сегмента і розмірів уже скопійованих у виконавчий файл сегментів. Ця адреса складається із зсуву і канонічного номера кадру. Канонічна адреса кадру визначає адреса першого параграфа в пам'яті, що містить один чи більш байтів сегмента. Номер кадру завжди кратний 16. Зсувом є відстань у байтах від початку параграфа до першого байта сегмента. Для типів PAGE і PARA зсув завжди нульовий, а для типів BYTE і WORD може бути ненульовим. Номер кадру може бути отриманий з MAP-файлу. Його містять перші 5 16-ричних цифр start-адреси сегмента.

Послідовність сегментів.

LINK копіює сегменти у виконавчий файл в такій же послідовності, у якій він їх зчитує з об'єктних файлів. Сегменти, що мають ідентичні імена класів, вважаються приналежними до одного типу класів і копіюються в виконавчий файл як безупинний блок. Порядок завантаження сегментів і способи керування цим порядком шляхом присвоювання типів класів обговорюються в п.3.4.3 MICROSOFT MACRO ASSEMBLER REFERENCE MANUAL.

Комбіновані сегменти.

Для визначення того, чи будуть два або більше сегментів, які мають те саме ім'я, з'єднані в один великий сегмент, LINK використовує комбінації типів сегментів. У мові асемблера маються наступні типи комбінацій: PUBLIC, STACK, COMMON, MEMORY, AT і PRIVATE (п.3.4.2 MICROSOFT MACRO ASSEMBLER REFERENCE MANUAL). Якщо сегмент має тип комбінації PUBLIC, LINK автоматично з'єднує його з іншими сегментами, що мають те ж ім'я і приналежні до того ж класу. При з'єднанні сегментів передбачається, що сегменти безупинні і всі адреси в сегментах доступні через зсув відносно адреси кадру. Результат виходить таким же, як якби отриманий великий сегмент був визначений у вихідному файлі суцільним шматком. LINK зберігає тип вирівнювання кожного сегмента. Це означає, що, хоча сегменти і включені в один великий сегмент, код і дані сегментів зберігають свої типи вирів- нювання. Якщо розміри сегментів, що з'єднуються, перевищують 64ДО, видається повідомлення про помилку. Якщо сегмент має тип комбінації STACK, LINK виконує ту ж операцію, що й у випадку PUBLIC. Розходження полягає в тому, що для STACK-сегментів у виконавчий файл записується початкове значення покажчика стека, яке являє собою зсув від кінця першого по порядку сегмента або стека комбінованого сегмента.

У цьому випадку при використанні типу STACK для сегментів стека програмісту немає необхідності передбачати в програмі завантаження регістра SS. Якщо сегмент має тип комбінації COMMON, LINK автоматично з'єднує його з іншими сегментами, що мають те ж ім'я і приналежними до того ж класу. Однак, коли LINK з'єднує загальні сегменти, початок кожного сегмента встановлюється на одну адресу, у результаті чого утворяться серії сегментів, що перекриваються. У підсумку виходить один сегмент, що по довжині не перевищує самий довгий з комбінуючих сегментів. Сегменти з типом комбінації MEMORY трактуються LINK у точності так само, як і PUBLIC-сегменти. MASM забезпечує MEMORY для сумісності з лінкерами тип, що виділяє MEMORY як особливий тип комбінації. Сегмент має тип комбінації PRIVATE у тому випадку, коли у вихідному файлі немає точних указівок відносно його типу комбінації. LINK не поєднує PRIVATE-сегменти.

Групи.

Об'єднання декількох сегментів у групу дозволяє адресувати їх щодо однієї адреси кадру. При цьому неважливо, чи належать ці сегменти до одного класу. Коли LINK виявляє групу, він відповідним чином перебудовує всі адресні посилання в ній. Сегменти в групі не є суміжними, не належать до одного класу і мають різні типи комбінацій. Але сумарний обсяг усіх сегментів у групі не повинний перевищувати 64ДО. Групи не впливають на порядок завантаження сегментів у пам'ять. Навіть якщо використовуються імена класів і об'єктні файли вводяться у відповідній послідовності, немає гарантії, що сегменти будуть суміжними. На практиці LINK може помістити не приналежній групі сегмент у ті ж 64ДО пам'яті. Хоча в LINK і немає строгої перевірки того, чи містяться усі сегменти групи в 64ДО пам'яті, але при виявленні порушення цієї умови буде видане повідомлення про переповнення узгодження.

Узгодження.

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

1. Короткі.

2. Внутрішні щодо себе.

3. Внутрішні щодо сегмента.

4. Довгі.

Розмір значення, що обчислюється, залежить від типу посилання. Якщо LINK виявляє помилку в передвіщеному розмірі посилання, видається повідомлення про переповнення узгодження. Це може відбутися, наприклад, коли програма намагається використовувати 16-бітовий зсув для доступу до інструкції в сегменті, що має інша адреса кадру. Це ж повідомлення може бути видано, якщо всі сегменти в групі не містяться усередині блоку пам'яті в 64ДО. Коротке посилання має місце в інструкції JMP, воно передає керування на позначену інструкцію в тому ж сегменті групи, що відстає від JMP не більш, ніж на 128 байтів. Для такого посилання LINK виробляє 8-бітове число зі знаком. Якщо інструкція, на яку передається керування, знаходиться в іншому сегменті чи групі, тобто має іншу адресу кадру, або відстає більш, ніж на 128 байтів у будь-якому напрямку, формується повідомлення про помилку.

Внутрішнє щодо себе посилання має місце в інструкціях, що адресують дані до того ж сегмента чи групи. Для такого посилання LINK формує 16-бітовий зсув. Якщо дані не належать тому ж сегменту чи групі, видається повідомлення про помилку. Внутрішнє щодо сегмента посилання має місце в інструкціях, що адресує дані у визначеному сегменті чи групі щодо зазначеного регістра сегмента. Для цього посилання LINK виробляє 16-бітовий зсув. Якщо цей зсув усередині специфікованого кадру виявляється більшим 64ДО і менше 0, чи якщо початок канонічного кадру, утримуючого необхідні дані – без адресації: видається повідомлення про помилку. Довге посилання має місце в інструкціях CALL, передавальних керування в інший сегмент чи групу. LINK у цьому випадку виробляє 16-бітову адресу кадру і 16-бітовий зсув. Якщо обчислений зсув більше 64ДО і менше 0, чи якщо початок канонічного кадру, у який передається керування – без адреси, формується повідомлення про помилку.

Пошук бібліотек.

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

1. У поточному підоголошенні.

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

3. На шляхах, визначених змінної LIB команди DOS SET. За допомогою команди SET можуть бути задані кілька шляхів пошуку, які діляться крапкою з комою. Вид команди SET: SET LIB=<список шляхів>.


Лекція 5 Основні поняття мови асемблера Х86


Будова програми на мові Assembler

Поняття "сегмент", "регістр", "підпрограмма"

Граматичні конструкції, які відповідають цим поняттям

Тип даних в асемблері. Поняття "байт", "півбайт", "слово", та інші


1. Будова програми на мові Assembler


ФОРМАТ КОДУВАННЯ

Основний формат кодування команд асемблера має наступний вигляд:


[мітка] команда [операнд(и)]


Мітка (якщо мається), команда й операнд (якщо мається) pозділяються принаймні одним пробілом або символом табуляції. Максимальна довжина рядка - 132 символи, однак, більшість бажають працювати з рядками в 80 символів (відповідно ширині екрана). Приклади кодування:


Мітка Команда Операнд

COUNT DB 1; Ім'я, команда, один операнд

MOV AX 0; Команда, два операнда


Мітки

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

Букви: від A до Z і від a до z.

Цифри: від 0 до 9.

Спецсимволи: знак питання (?) крапка (.) (тільки перший символ) знак "комерційне эт" (@) підкреслення (-) долар ($).

Першим символом у мітці повинна бути буква спецсимвол. Асемблер не робить розходження між заголовними і рядковими буквами. Максимальна довжина - 31 символ. Приклади міток: COUNT, PAGE25, $E10. Рекомендується використовувати описові і значеневі мітки. Імена регістрів, наприклад, AX, DI чи AL є зарезервованими і використовуються тільки для вказівки відповідних регістрів. Наприклад, у команді ADD AX, BX асемблер "знає", що AX і BX відноситься до регістрів. Однак, у команді MOV REGSAVE,AX асемблер сприйме ім'я REGSAVE тільки в тому випадку, якщо воно буде визначено в сегменті даних. У додатку 3 приведений cписок усіх зарезервованих слів асемблера.

Команда

Мнемонічна команда вказує асемблеру яку дію повинен виконати даний оператор. У сегменті даних команда (чи директива) визначає поле, робочу oбласть чи константу. У сегменті коду команда визначає дію, наприклад, пересилання (MOV) чи додавання (ADD).

Операнд

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


Мітка Команда Операнд

COUNTER DB 0;

Визначити байт (DB); з нульовим значенням.


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


Команда Операнд Коментар

Немає операндів RET; Повернутися

Один операнд INC CX ;Збільшити CX

Два операнда ADD AX,12 ;Додати 12 до AX


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


2. Поняття "сегмент", "регістр", "підпрограмма"


Сегментом називається область, що починається на границі параграфа, тобто по будь-якій адресі, що поділяється на 16 без залишку. Хоча сегмент може розташовуватися в будь-якому місці пам'яті і мати розмір до 64 Кбайт, він вимагає стільки пам'яті, cкільки необхідно для виконання програми. Існує три головних сегменти:

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

2. Сегмент даних. Сегмент даних містить визначені дані, константи і робочі області, необхідні програмі. Регістр сегмента даних (DS) адресує даний сегмент.

3. Сегмент стека. Стік містить адреси повернення як для програми для повернення в операційну систему, так і для викликів підпрограм для повернення в головну програму.

Регістр сегмента стека (SS) адресує даний сегмент.

Ще один сегментний регістр - регістр додаткового сегмента (ES), призначений для спеціального використання. На pис.1.2 графічно представ- лені регістри SS, DS і CS.

Послідовність регістрів і сегментів на практиці може бути інша. Три сегментних регістри містять початкові адреси відповідних сегментів і кожен сегмент починається на границі параграфа. Усередині програми всі адреси пам'яті відносні до початку cегмента. Такі адреси називаються зсувом від початку сегмента. Двобайтовий зсув (16-бітний) може бути в межах від значення 0000 до значення FFFF або від 0 до 65535. Для звертання до будь-якої адреси в програмі, комп'ютер складає адреса в регістрі сегмента і зсуву. Наприклад, перший байт у сегменті кодів має зсув 0, другий байт - 01 і так далі до зсуву 65535. Як приклад адресації, допустимо, що регістр сегмента даних містить значення 045F і деяка команда звертається до комірки пам'яті усередині сегмента даних з зсувом 0032. Недивлячись на те, що регістр сегмента даних містить 045F, він вказує на адресу 045F0, тобто на границі параграфа. Дійсний aдрес пам'яті тому буде наступний:

Адреса в DS: 045F0

Зсув: 0032

Реальна адреса: 04622

Яким чином процесори 8086/8088 адресують пам'ять в один мільйон байт? У регістрі міститься 16 біт. Оскільки адреса сегмента завжди на границі параграфа, молодші чотири біти адреси pівні нулю. Тичина. FFF0 дозволяє адресувати до 65520 (плюс зсув) байт. Але фахівці вирішили, що нема рації мати місце для бітів, що завжди дорівнюють нулю. Тому адреса зберігаються в cегментному регістрі як шіст. nnnn, а комп'ютер думає, що існує ще чотири нульових молодших біта (одна шіст. цифра), тобто шіст. nnnn0. Таким чином, тичина. FFFF0 дозволяє адресувати до 1048560 байт. Якщо ви сумніваєтесь, то декодуйте кожне тичина. F як двійкове 1111, врахуйте нульові біти і складете значення для одиничних біт. Процесор 80286 використовує 24 біта для адресації так, що FFFFF0 дозволяє адресувати до 16 мільйонів байт, а процесор 80386 може адресувати до чотирьох мільярдів байт.

3. Граматичні конструкції, які відповідають цим поняттям


РЕГІСТРИ

Процесори 8086/8088 мають 14 регістрів, використовуваних для yправления програмою, що виконується, для адресації пам'яті і для забезпечення арифметичних обчислень. Кожен регістр має довжину в одне слово (16 біт) і адресується по імені. Біти регістра прийняті нумерувати ліворуч праворуч:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Процесори 80286 і 80386 мають ряд додаткових регістрів, деякі з них 16-бітові. Ці регістри тут не розглядаються. Сегментні регістри CS, DS, SS і ES.

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

Регістр CS.

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

Регістр DS.

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

3. Регістр SS.

Регістр сегмента стека містить початковий адрес в сегменті стека.

4. Регістр ES. Деякі операції над рядками використовують додатковий сегментний регістр для керування адреси цієї пам'яті. У даному контексті регістр ES зв'язаний з індексним регістром DI. Якщо необхідно використовувати регістр ES, асемблерна програма повинна його інніціалізувати.

Регістри загального призначення: AX, BX, CX і DX

При програмуванні на асемблере регістри загального призначення є "робочими конячками". Особливість цих регістрів полягає в тому, що можлива адресація їх як одного цілого чи слова як oднобайтової частини. Лівий байт є старшою частиною (high), a правий - молодшою частиною (low). Наприклад, двобайтовий регістр CX складається з двох однобайтових: CH і CL, і посилання на регістр можливі по кожному з цих трьох імен. Наступні три асемблерні команди засилають нулі в регістри CX, CH і CL, відповідно:


MOV CX,00

MOV CH,00

MOV CL,00


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


AX: ¦ AH ¦ AL ¦


2. Регістр BX. Регістр BX є базовим регістром. Це єдиний регістр загального призначення, що може використовуватися в якості "індексу" для розширеної адресаціі. Інше загальне застосування його - обчислення.


BX: ¦ BH ¦ BL ¦


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


CX: ¦ CH ¦ CL ¦


4. Регістр DX. Регістр DX є регістром даних. Він застосовується для деяких операцій уведення/висновку і тих операцій множення і розподілу над великими числами, які використовують реєстрову пару DX і AX.


DX: ¦ DH ¦ DL ¦


Будь-які регістри загального призначення можуть використовуватися для додаваня і вирахування як 8-ми, так і 16-ти бітових значень.

Реєстрові покажчики: SP і BP

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

1. Регістр SP. Покажчик стека забезпечує використання стека в пам'яті, дозволяє тимчасово зберігати адреса і інколи дані. Цей регістр зв'язаний з регістром SS для адреси цього стека.

2. Регістр BP. Покажчик бази полегшує доступ до параметрів: даним і адресам переданим через стек.

Індексні регістри: SI і DI

Обоє індексні регістри можливі для розширеної адресації і для використа- ння в операціях додавання і вирахування.

1. Регістр SI. Цей регістр є індексом джерела і застосовується для деяких операцій над рядками. У даному контексті регістр SI зв'язаний з регістром DS.

2. Регістр DI. Цей регістр є індексом призначення і застосовується також для строкових операцій. У даному контексті регістр DI зв'язаний з регістром ES.

Регістр командного покажчика: IP

Регістр IP містить зсув на команду, що повинна бути виконана. Звичайно цей регістр у програмі не використовується, але він може змінювати своє значення при використанні відлагоджувача DOS DEBUG для тестування програми.

Флаговий регістр

Дев'ять з 16 бітів флагового регістра є активними і визначають поточний стан машини і результати виконання. Багато арифметичних команд і команди порівняння змінюють стан прапорів. Призначення флагових бітів:

Прапор Призначення

O (Переповнення) Вказує на переповнення старшого біта при арифметичних командах.

D (Напрямок) Позначає ліве чи праве направлення чи пересилання порівняння строкових даних (даних у пам'яті перевищуючих довжину одного слова).

I (Переривання) - Вказує на можливість зовнішніх переривань.

T (Покроковий режим) - Забезпечує можливість роботи процесора в покроковому режимі.

Наприклад, програма DOS DEBUG впливає на даний прапор так, що ймовірне покрокове виконання кожної команди для перевірки зміни вмісту регістрів і пам'яті.

S (Знак) Містить результуючий знак після арифметичних операцій (0 - плюс, 1 - мінус).

Z (Нуль) Показує результат арифметичних операцій і операцій порівняння (0 - ненульовий, 1 - нульовий результат).

A (Зовнішній перенос) Містить перенос з 3-го біта для 8-бітних даних, використовується для спеціальних арифметичних операцій.

P (Контроль парності) Показує парність молодших 8-бітних даних (1 - парне і 0 - непарне число).

C (Перенос) Містить перенос зі старшого біта, після арифметичних операцій, а також останній біт при зрушеннях або циклічних зрушеннях.

Під час програмування на асемблері, частіше всього використовуються прапори O, S, Z, і C для арифметичних операцій і операцій порівняння, а прапор D для позначення напрямку в операціях над рядками. У наступних розділах міститься більш докладна інформація про флаговий pегістр.


4. Тип даних в асемблері. Поняття "байт", "півбайт", "слово", та інші


ДИРЕКТИВИ ВИЗНАЧЕННЯ ДАНИХ

Асемблер забезпечує два способи визначення даних : по-перше, через указівку довжини даних і, по-друге, по їх змісту. Розглянемо основний формат визначення даних:

[ім'я] Dn вираження - Ім'я елемента даних не обов'язково (це вказується квадратними дужками), але якщо в програмі існують посилання на деякий елемент, то це робиться за допомогою імені. Правила написання імен приведені в розділі "Формат кодування" у розділі 3.

- Для визначення елементів даних існують наступні директиви: DB (байт), DW (слово), DD (подвійне слово), DQ (учетверенное слово) і DT (десять байт).

- Вираження може містити константу, наприклад: FLD1 DB 25 чи знак питання для невизначеного значення, наприклад: FLDB DB ?

Вираження може містити кілька констант, розділених комами й обмеженими тільки довжиною рядка: FLD3 DB 11, 12, 13, 14, 15, 16, ...

Асемблер визначає ці константи у виді послідовності суміжних байт. Посилання по імені FLD3 вказує на першу константу, 11, по FLD3+1 - на другу, 12. (FLD3 можна представити як FLD3+0). Наприклад команда MOV AL,FLD3+3 завантажує в регістр AL значення 14 (тичина. 0E). Вираження допускає також повторення константи в наступному форматі:

[ім'я] Dn чисел-повторень DUP (вираження) ...

Наступні три приклади ілюструють повторення:

DW 10 DUP(?); Десять невизначених слів

DB 5 DUP(14); П'ять байт, що містять тичину.14

DB 3 DUP(4 DUP(8)); Дванадцять вісімок.

У третьому прикладі спочатку генерується чотири копії десяткової 8 (8888), і потім це значення повторюється три рази, даючи в pезультате дванадцять восмерок. Вираження може містити символьний чи рядок числову константу.

Символьні рядки

Символьний рядок використовуються для опису даних, таких як, наприклад, імена людей або заголовки сторінок. Зміст рядка відмічається одиночними лапками , наприклад, 'PC' або подвійними лапками - "PC". Асемблер переводить символьні рядки в об'єктний код у звичайному форматі ASCII. Символьний рядок визначається тільки директивою DB, в якій вказується більше двох символів у нормальній послідовності ліворуч праворуч. Отже, директива DB представляє єдиний можливий формат для визначення символьних даних. На рис. 5.1 приведений ряд прикладів.

Числові константи

Числові константи використовуються для арифметичних величин і для aдресів пам'яті. Для опису константи лапки не ставляться. Асемблер перетворить усі числові константи в шістнадцяткові і записує байти в об'єктному коді в зворотній послідовності - праворуч ліворуч. Нижче показані різні числові формати.

Десятковий формат.

Десятковий формат допускає десяткові цифри від 0 до 9 і позначається останньою буквою D, що можна не вказувати, наприклад, 125 чи 125D. Незважаючи на те, що асемблер дозволяє кодування в десятковому форматі, він перетворить ці значення в шіст. об'єктний код. Наприклад, десяткове число 125 перетвориться в тичину. 7D. Шістнадцятковий формат.

Шістнадцятковий формат допускає шістнадцяткові цифри від 0 до F і позначається останньою буквою H. Оскільки асемблер думає, що з букви починаються ідентифікатори, то першою цифрою шіст. константи повинна бути цифра від 0 до 9. Наприклад, 2EH або 0FFFH, вказують на те, що асемблер перетворить відповідно в 2E і FF0F (байти в другому прикладі записуються в об'єктний код у зворотній послідовності).

Двійковий формат.

Двійковий формат допускає двійкові цифри 0 і 1 і позначається останньою буквою B. Двійковий формат звичайно використовується для більш чіткого представлення бітових значень у логічних командах AND, OR, XOR і TEST. Десяткове 12, тичина. C і двійкове 1100B усі генерують один і той же код: тичина. 0C або двійкове 0000 1100 в залежності від того, як ви розглядаєте вміст байта.

Вісімковий формат.

Вісімковий формат допускає вісімкові цифри від 0 до 7 і позначається останньою буквою Q чи O, наприклад, 253Q. На сьогодні вісімковий формат використовується дуже рідко.

Десятковий формат із крапкою, що плаває.

Цей формат підтримується тільки асемблером МASM. При записі символьних і числових констант потрібно пам'ятати, що, наприклад, символьна константа, визначена як DB '12', представляє символи ASCII і генерує тичина. 3132, а числова константа, визначена як DB 12, вставляє двійкове число і генерує тичина. 0C. Рис. 5.1 ілюструє директиви для визначення різних символьних рядків і числових констант. Сегмент даних був асемблюваний для того, щоб показати згенерований об'єктний код (ліворуч).

ДИРЕКТИВА ВИЗНАЧЕННЯ БАЙТА (DB)

З різних директив, що визначають елементи даних, найбільш корисної є DB (визначити байт). Символьне вираження в диpективе DB може містити рядок символів будь-якої довжини, аж до кінця рядка (див. FLD2DB і FLD7DB на рис. 5.1). Зверніть увагу, що константа FLD2DB містить символьний рядок 'Personal Computer'. Об'єктний код показує символи коду ASCII для кожного байта. Тичина. 20 представляє символ пробілу. Числове вираження в директиві DB може містити одну чи більше однобайтних констант. Один байт виражається двома цифpами. Найбільше позитивне шіст. число в одному байті це 7F, усі "великі" числа від 80 до FF представляють негативні значення. У десятковому численні ці межі виражаються числами +127 і -128. У прикладі на рис. 5.1 числовими константами є FLD3DB, FLD4DB, FLD5DB і FLD8DB. Поле FLD6DB представляє суміш з числових і строкових констант, які використовуються для побудови таблиці.

ДИРЕКТИВА ВИЗНАЧЕННЯ СЛОВА (DW)

Директива DW визначає елементи, що мають довжину в одне слово (два байти). Символьне вираження в DW обмежено двома символами, що асемблер представляє в об'єктному коді так, що, наприклад, 'PC' стає 'CP'. Для визначення символьних рядків директива DW має обмежене застосування. Числове вираження в DW може містити одне або більше двобайтних констант. Два байти представляються чотирьма тичина. цифрами. Найбільше позитивне шіст. число в двох байтах це 7FFF; усі "великі" числа від 8000 до FFFF представляють негативні значення. У десятковому численні ці межі виражаються числами +32767 і -32768.

У прикладі на рис. 5.1 поля FLD1DW і FLD2DW визначають числові константи. Поле FLD3DW визначає адреса - у даному випадку зсув на адресу FLD7DB. У результаті генерується об'єктний код 0021 (R позначає перемещаемость). Перевіряючи вище по малюнку, видно, що відносна адреса поля FLD7DB дійсно 0021. Поле FLD4DW визначає таблицю з п'яти числових констант. Помітимо, що об'єктний код для кожної константи має довжину в одне слово (два байти). Для форматів директив DW, DD і DQ асемблер перетворить константи в шест. об'єктний код, але записує його в зворотній послідовності. У такий спосіб десяткове значення 12345 перетвориться в тичину.3039, але записується в об'єктному коді як 3930.

ДИРЕКТИВА ВИЗНАЧЕННЯ ПОДВІЙНОГО СЛОВА (DD)

Директива DD визначає елементи, що мають довжину в два cлова (чотири байти). Числове вираження може містити одну чи більше констант, кожна з який має максимум чотири байти (вісім шест. цифр). Найбільше позитивне шіст. число в чотирьох байтах це 7FFFFFFF; усі "великі" числа від 80000000 до FFFFFFFF представляють негативні значення. У десятковому численні ці межі виражаються числами +2147483647 і -2147483648. У прикладі на рис. 5.1 поле FLD3DD визначає числову константу. У полі FLD4DD генерується різниця між двома адресами, у даному випадку результатом є довжина поля FLD2DB. Поле FLD5DD визначає дві числові константи. Асемблер перетворить усі числові константи в директиві DD у шіст. представлення, але записує об'єктний код у зворотній послідовності. У такий спосіб десяткове значення 12345 перетвориться в тичину. 00003039, але записується в об’єктному коді як 39300000. Символьне вираження директиви DD обмежене двома символами. Асемблер перетворить символи і вирівнює їх ліворуч у чотирьохбайтному подвійному слові, як показано в полі FLD2DD в об'єктному коді.

ДИРЕКТИВА ВИЗНАЧЕННЯ УЧЕТВЕРЕННОГО СЛОВА (DQ)

Директива DQ визначає елементи, що мають довжину чотири слова (вісім байт). Числове вираження може містити одну чи більш констант, кожна з який має максимум вісім байт або 16 шіст.цифр. Найбільше позитивне тичина. число - це сімка і 15 цифр F. Для одержання представлення про величину цього числа, покажемо, що тичина. 1 і 15 нулів еквівалентний наступному десятковому числу: 1152921504606846976.

У прикладі на рис. 5.1 поля FLD2DQ і FLD3DQ ілюструють числові значення. Асемблер перетворить усі числові кін станты в директиві DQ у шест. представлення, але записує об'єктний код у зворотній послідовності, як і в директивах DD і DW. Обробка асемблером символьних рядків у директиві DQ aналогічно директивам DD і DW.

ДИРЕКТИВА ВИЗНАЧЕННЯ ДЕСЯТИ БАЙТ (DT)

Директива DT визначає елементи даних, що мають довжину в десять байт. Призначення цієї директиви зв'язане з "упакованими десятковими" числовими величинами (див. гл.13). По директиві DT генеруються різні константи, у залежності від версії асемблера; для практичного застосування ознайомтеся з посібником з вашому aссемблера. На рис. 5.1 приведені приклади директиви DT для невизначеного елемента і для двосимвольної константи. Програма на рис.5.1 містить тільки сегмент даних. Xоча асcемблер не видає повідомлень про помилки, у таблиці LINK MAP з'явиться попередження: "Warning: No STACK Segment", а компоновщик LINK видасть "There were 1 errors detected" (Виявлена 1 помилка). Незважаючи на це попередження можна використовувати відлагоджувач DEBUG для перегляду об'єктного коду, як показано на рис. 5.2. Права сторона дампа чітко показує символьні дані, як, наприклад, "Personal Computer".

БЕЗПОСЕРЕДНІ ОПЕРАНДИ

На рис. 2.1 у розділі 2 було показано використання безпосередніх операндів. Команда MOV AX,0123H пересилає безпосередню шіст. константу 0123 у регістр AX. Трьохбайтний об'єктний код для цієї команди є B82301, де B8 позначає "переслати безпосереднє значення в регістр AX", a наступні два байти містять саме значення. Багато команд мають два операнди: перший може бути регістр адреси або пам'яті, а другий - безпосередньо константа.

Використання безпосереднього операнда є ефективнішим ніж визначення числової константи в сегменті даних і організації зсилки на неї в операнді команди MOV, наприклад, cегмент даних: AMT1 DW 0123H? cегмент кодів: MOV AX,AMT1.

Довжина безпосередніх операндів.

Довжина безпосередньої константи залежить від довжини першого операнда. Наприклад, якщо випливає що безпосередній операнд є двобайтним, регістр AL має тільки один байт: MOV AL,0123H (помилка) однак, якщо безпосередній операнд коротший, ніж той що одержує операнд, як у наступному прикладі - ADD AX,25H (немає помилки) то асемблер розширює безпосередній операнд до двох байт, 0025 і записує об'єктний код у вигляді 2500.

Безпосередні формати

Безпосередня константа може бути шістнадцятковою, напpиклад, 0123H; десятковою, наприклад, 291 (яку асемблер конвертує в тичину.0123); чи двійковою, наприклад, 100100011В (яка перетвориться в тичину. 0123). Нижче приведений список команд, що допускають безпосередні операнди:

Команди пересилання і порівняння: MOV, CMP.

Арифметичні команди: ADC, ADD, SBB, SUB.

Команди зрушення: RCL, RCR, ROL, ROR, SHL, SAR, SHR.

Логічні команди: AND, OR, TEST, XOR.

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

ДИРЕКТИВА EQU

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


TIMES EQU 10


Ім'я, у даному випадку TIMES, може бути представлено будь-яким припустимим в асемблері ім'ям. Тепер, в якій-би команді чи директиві не використовувалося слово TIMES асемблер підставить значення 10. Наприклад, асемблер перетворить директиву - FIELDA DB TIMES DUP (?) у FIELDA DB 10 DUP (?).

Ім'я, зв'язане з деяким значенням за допомогою директиви EQU, може використовуватися в командах, наприклад:


COUNTR EQU 05

MOV CX,COUNTR


Асемблер заміняє ім'я COUNTR у команді MOV на значення 05, створюючи операнд із безпосереднім значенням, так, нібито він закодований.


MOV CX,05; Асемблер підставляє 05


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

1. TP EQU TOTALPAY

2. MPY EQU MUL

Перший приклад припускає, що в сегменті даної програми визначено ім'я TOTALPAY. Для будь-якої команди, що містить операнд TP, асемблер замінить його на адресу TOTALPAY. Другий приклад показує можливість використання в програмі слова MPY замість звичайного мнемокоду MUL.


Лекція 6 Транслятори мови Assembler


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

TASM

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

Turbo Assembler Version 2.0 Copyright (C) 1990

by Borland International, Inc

Usage:

TASM [параметри] исх_файл [,об'єкт_файл] [,лістинг] [,пер_посилання]

/a,/s Упорядкованість сегментів за алфавітним порядком чи порядку вихідного коду /c Генерація в лістингу перехресних посилань

/dSYM[=VAL] Визначається SYM = 0 чи SYM = VAL

/e,/r Эмулируемые чи дійсні інструкції з плавающей крапкою

/h,/? Виводиться дана довідкова інформація

/lPATH файли, що включаються, шукаються по маршруті, обумовленому PATH

/jCMD Визначає початкову директиву Асемблера (напримір, jIDEAL)

/kh#,/ks# Потужність хеш-таблицы #, потужність обсягу рядка #

/l,/la Генерація лістинга: l=звичайний лістинг, la=розширенаный

/ml,/mx,/mu Розрізнення в регістрі букв ідентифікаторів: ml=усі, mx=глобальні, mu=не розрізняються

/mv# Задає максимальну довжину ідентифікаторів

/m# Дозволяє виконання декількох проходів для зодоволення випереджальних посилань

/n Придушення в лістингах таблиці символів (ідентифікаторів)

/p Перевірка перекриття сегмента коду в захищеному режимі

/q Придушення записів .OBJ, що не вимагаються при компоновке

/t Придушення повідомлень при успішному асемблировании

/w0,/w1,/w2 Завдання рівня попередження: w0=немає попереджень, w1=w2=є попередження

/w-xxx,/w+xxx чи Заборона дозвіл попередження типу xxx

/x Включення в лістинги блоків умовного асемблирования

/zi,/zd Інформація про ідентифікатори для налагодження: zi=підлоганая, zd=тільки про номери рядків.

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

Загальний вид командного рядка виглядає в такий спосіб:


TASM файли [; файли]...


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


TASM /E FILE1; /A FILE2


У загальному випадку група файлів у командному рядку може мати вигляд:


[параметр]...исх_файл [[+] вихідний_файл]...

[,[об'єктний_файл] [, [файл_лістинга],

[, [файл_перехресних_посилань]]


Цей синтаксис показує, що група файлів може починатися з будь-якого параметра, що ви хочете застосувати до цих файлів а потім можуть випливати файли, що ви хочете асемблировать. Ім'ям файлу може бути одне ім'я файлу, або ви можете використовувати звичайні трафаретні символи DOS * і ? для завдання групи ассемблируемых файлів. Якщо розширення імені файлу не зазначено, Турбо Асемблер використовує за замовчуванням розширення ".ASM".


TASM MYFILE,,,MYXREF


По цій команді файл MYFILE.ASM асемблируется у файл MYFILE.OBJ, лістинг виводиться у файл з ім'ям MYFILE.LST, а перекрестные посилання - у файл MYXREF.XRF.

Якщо при специфікації асемблируемых вихідних файлів ви используете трафаретні символи, їх можна використовувати також для завдання імен файлу лістинга й об'єктного файлу. Наприклад, якщо в поточному каталозі містяться файли XX1.ASM і XX2.ASM, то командний рядок:


TASM XX*,YY*


асемблює усі файли, що починаються з букв XX, генерує об’єктні файли, імена яких будуть починатися з YY, а іншу частина імені формує відповідно до імені вихідного файлу. Результуючі об'єктні файли одержать, таким чином, імена YY1, OBJ і YY2.OBJ.

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


TASM FILE1,,NUL,


Ця команда асемблирует файл FILE1.ASM в об'єктний файл FILE1.OBJ. При цьому файл лістинга не створюється, а створюється файл перехресних посилань FILE1.XRF.

Параметри командного рядка

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

/B Задає розмір буфера

/V Виводить на екран додаткову статистику

Ви можете задавати параметри, що представляють собою будь-яку комбінацію букв у верхньому і нижньому регістрі. Крім того, параметри можна задавати в будь-якому порядку (крім параметрів /I і /J), вони будуть при цьому оброблятися послідовно. При використанні параметра /D потрібно бути уважним: ідентифікатори треба визначити до того, як вони будуть використані в наступних параметрах /D.

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

На Рис. 3.1 (см. вище) приведений список параметрів Турбо Ассемблера. Далі ці параметри описані докладно (їх можна також задавати буквами в нижньому регістрі).

Параметр /A

Функція: Задає упорядкованість сегментів по алфавітному порядку.

Синтаксис: /A

Примітки: Параметр /A вказує Турбо Асемблеру, що сегменты в об'єктному файлі повинні бути розміщені в алфавітному порядке. Це еквівалентно використанню у вихідному коді директиви .ALPHA. Цим параметром звичайно приходиться користатися тоді, коли ви хочете асемблировать вихідний файл, написаний для ранніх версій асемблеров фірм Microsoft чи IBM.

Параметр /S змінює дія даного параметра на зворотне, зберігаючи використовуване за замовчуванням послідовне упорядочивание сегментів.

Якщо у вихідному файлі ви задаєте за допомогою директиви .SEQ послі довне упорядочивание сегментів, то вона скасує действие параметра /A, що задається в командному рядку.

Приклад : TASM /A TEST1

Даний командний рядок створює об'єктний файл TEST1.OBJ, сегменти якого упорядковуються за абеткою.

Параметр /B

Синтаксис: /B

Примітки: Параметр /B використовується тільки з метою совместимости з іншими версіями. Він не приводить ні до яких дій і не робить впливу на асемблювання.

Параметр /C

Функція: Дозволяє включати в лістинг перехресні посилання.

Синтаксис: /C

Примітки: Параметр /C дозволяє включення у файл лістинга інформації про перехресні посилання. Турбо Асемблер включає информацію про перехресні посилання в таблицю ідентифікаторів наприкінці файлу лістинга. Щоб одержати інформацію про перехресні посилання, вам потрібно також явно задати в командному рядку генерацію файлу лістинга чи викори- стовувати для дозволу формування файлу лістинга параметр /L.

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

Параметр /D

Функція: Визначає ідентифікатор.

Синтаксис: /Dидентификатор[= чизначення вираження]

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

Ви можете тільки визначити ідентифікатор, рівний іншому ідентифі- катору, чи постійному значенню. Праворуч від знака равенства (=) не допускається використовувати вираження з операціями. Наприклад, припу- стиме /DX=9 і /DX=Y, але параметр /DX=Y-4 не допускається.

Приклад:


TASM /DMAX=10 /DMIN=2 TEST1


У даному командному рядку визначаються два ідентифікатори MAX і MIN, на які можуть посилатися інші оператори у вихідному файлі TEST1.ASM.

Параметр /E

Функція: Генерує інструкції эмуляции роботи з що плаває крапкою.

Синтаксис: /E

Примітки: Параметр /E вказує Турбо Асемблеру, які потрібно генерувати інструкції роботи з крапкою, що плаває, яка буде виконуватися за допомогою програмного забезпечення (емулятора операцій із крапкою, що плаває,). Використовуйте цей параметр, якщо ваша програма містить бібліотеку эмуляции роботи з що плаває крапкою, що эмулирует функції арифметичного співпроцесора 80х87. Звичайно цей параметр варто викори- стовувати тільки в тому випадку, якщо ваш модуль на Асемблері є частиною програми, написаної мовою високого рівня, у якій використовується бібліо-тека емуляціі роботи з крапкою, що плаває, (емуляцію операцій із пла-ваючою крапкою підтримують Турбо Сі, Турбо Паскаль, Турбо Бейсік і Турбо Пролог). Ви не можете просто скомпонувати програму на Асемблері з бібліотекою емуляціі, тому що передбачається, що бібліотека повинна ініціалізуватися початковим кодом компілятора.

Параметр /R змінює дію даного параметра на зворотню, дозволяючи асемблювання дійсних інструкцій із плаваючою крапкою, що можуть виконуватися арифметичним співпроцесором. Якщо у вихідному файлі ви використовуєте директиву NOEMUL, то вона скасує дію параметра /E у командному рядку.

Параметр командного рядка /E робить ту ж дію, що і використання на початку вихідного файлу директиви EMUL, і еквівалентний параметру командного рядка /JEMUL.

Приклад:


TASM /E SEGANT

TCC -f TRIG.C SEGANT.OBJ


Параметр /H чи /?

Функція: Виводить на екран дисплея довідкову інформацію.

Синтаксис: /H чи /?

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

Параметр /I

Функція: Задає маршрут доступу до файлу, що включається.

Синтаксис: /Iмаршрут

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

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

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

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

Приклад:


TASM /I\INCLUDE /ID:\INCLUDE TEST1


Якщо вихідний файл містить оператор:


INCLUDE MYMACS.INC


тоді Турбо Асемблер спочатку шукає файл \INCLUDE\MYMACS.INC, потім D:\INCLUDE\MYMACS.INC. Якщо він ще не знайшов файл, то файл с ім'ям MYMACS.INC шукається в поточному каталозі. Якби у вихідному файлі містився оператор:


INCLUDE INCS\MYMACS.INC


тоді Турбо Асемблер спочатку шукав файл, що би включається \INCS\ MYMACS.INC, потім \INCLUDE\MYMACS.INC,і, нарешті D:\INCLUDE\ MYMACS.INC.

Параметр /J

Функція: Визначає директиву ініціалізації Асемблера.

Синтаксис: /Jдиректива

Примітки: Параметр /J дозволяє вам визначити директиву, яка буде асемблироваться перед першим рядком вихідного файлу. "Директива" може являти собою будь-яку директиву Турбо Асемблера, не потребуючих аргументів, наприклад, .286, IDEAL, %MACS, NOJUMP і т.д. Повний опис директив Турбо Асемблера міститься в "Довідковому посібнику" у Главі 3.

У командному рядку ви можете вказати більше одного параметра /J. При цьому вони будуть оброблені ліворуч праворуч.

Приклад:


TASM /J.286.JIDEAL TEST1


При цьому асемблюється файл TEST1.ASM з дозволеними інструкціями процесора 80286 і дозволом синтаксичного аналізу виражень у режимі IDEAL.

Параметр /KH

Функція: Задає максимально припустиме число ідентифікаторів.

Синтаксис: /KHn-ідентифікаторів

Примітки: Параметр /KH задає максимально припустиме число ідентифікаторів, що може містити програма. Якщо ви не використовуєте даний параметр, ваша програма може містити толь до до 8192 іденти- фікаторів. Використання цього параметра дозволяє збільшити число ідентифікаторів до значення "n-ідентифікаторів" (це значення не повинне перевищувати 32768).

Використовуйте даний параметр, якщо при асемблюванні програми ви отримаєте повідомлення "Out of hash space" (буферний простір вичерпано).

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

Приклад:


TASM /KH10000 BIGFILE


Параметр /KS

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

Синтаксис: /KHkбайт

Примітки: Звичайно розмір рядка визначається автоматично і набудо- вувати його не потрібно. Однак якщо у вас існує файл результату, що приводить до повідомлення "Out of string space" (не вистачає строкового простору), те за допомогою даного параметра ви можете збільшити строковий простір. Спробуйте почати з значення 100 і збільшувати його, поки ваша програма не буде ассемблироваться без помилки. Максимально припустиме значення (у килобайтах) - 255.

Приклад:


TASM /KS150 SFILE


Параметр /L

Функція: Генерує файл лістинга.

Синтаксис: /L

Примітки: Параметр /L вказує, що ви хочете створити файл лістинга, навіть якщо ви його явно не задаєте в командному рядку . Файл лістинга має те ж ім'я, що і вихідний файл, і розширення LST.

Приклад:


TASM /L TEST1


Даний командний рядок приводить до створення файлу лістинга з ім'ям TEST1.LST.

Параметр /LA

Функція: Показує у вихідної файлі код інтерфейсу з мовою високого рівня.

Синтаксис: /LA

Примітки: Параметр /LA вказує Турбо Асемблеру, що в файлі лістинга потрібно відбити весь генерируемый код, включаючи код, який генерується в результаті директиви мови високого рівня .MODEL.

Приклад:


TASM /LA FILE1


Параметр /M

Функція: Задає максимальне число проходів Асемблера.

Синтаксис: /M[число_проходів]

Примітки: Звичайно Турбо Асемблер працює, як однопрохідный асемблер. Необов'язковий параметр /m дозволяє вам задати максимальне число прохо- дів, що Асемблер повинний виконувати в процесі асемблирования. Турбо Асемблер TASM автоматично определяет, що він може виконати менше заданого числа проходів.

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

"Pass-dependent construction encountered"

(виявлена конструкція, що залежить від проходу)

Якщо зазначений параметр /m, то Турбо Асемблер буде правильно асемблювати такий модуль, але не буде оптимізовувати код програми, видаляючи операції NOP (незалежно від зазначеного числа проходів). У цьому випадку виводиться повідомлення:

"Module is pass dependent - compatibility pass was done"

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

Приклад:


TASM /M2 TEST1


Ця команда вказує TASM, що асемблюваня модуля TEST1 потрібно виконувати в два проходи.

Параметр /ML

Функція: Інтерпретує розходження в регістрах букв ідентифікаторів.

Синтаксис: /ML

Примітки: Параметр /ML вказує Турбо Асемблеру, що в всіх ідентифі- каторах потрібно розрізняти букви різного регістра (рядкові і прописні). Звичайно рядкові і прописні букви рассматриваются, як еквівалентні, тому імена ABCxyz, ABCXYZ і abcxyz позначають той самий ідентифікатор. Якщо ви задаєте параметр /ML, те ці три ідентифікатори будуть вважатися різними. Проте, навіть після завдання параметра /ML ключові слова Асемблера можна вводити як у верхньому, так і в нижньому регістрі. Ключові слова являють собою идентификаторы, убудовані в Асемблер, що мають спеціальне значення (мнемоніки інструкцій, директиви й оператори).

Приклад:


TASM /ML TEST1


де TEST1.ASM містить наступні оператори:


ABC DW 1; це не дублюючий ідентифікатор

abc DW 0; у ключових словах допускається використовувати різний

Mov Ax,[Bp] регістр

Параметр /MU

Функція: Перетворить ідентифікатори у верхній регістр.

Синтаксис: /MU

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

Приклад:


TASM /MU TEST1


При цьому всі ідентифікатори будуть перетворені у верхній регістр (що задано за замовчуванням):


EXTRN myfunc:NEAR

call myfunc;


не важливо, як була визначена функція: MYFUNC, Myfunk,...

Параметр /MV#

Функція: Задає максимальну довжину ідентифікаторів.

Синтаксис: /MV#

Примітки: Даний параметр задає максимальну довжину идентифи- каторов, що буде розрізняти TASM. Наприклад, при завданні параметра /mv3 TASM буде інтерпретувати ідентифікатори ABCC і ABCD, як той самий ідентифікатор.

Параметр /MX

Функція: Задає розрізнення на на рядкові і прописні букви (верхній і нижній регістр) у зовнішніх і загальнодоступних идентификаторах.

Синтаксис: /MX

Примітки: Параметр /MX повідомляє Турбо Асемблеру, що различать регістр букв потрібно тільки в зовнішніх (External) і общедоступных (Public) ідентифікаторах. Всі інші ідентифікатори в исходном файлі будуть інтерпретуватися, як набрані у верхньому регістрі.

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

Приклад:


TASM /MX TEST1


де TEST1 містить наступні вихідні рядки:


EXTRN Cfunc:NEAR

myproc PROC NEAR

call Cfunc


Параметр /N

Функція: Придушує у файлі лістинга таблицю ідентифікаторів.

Синтаксис: /N

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

Ви повинні задати файл лістинга або явно (у командной рядку), або за допомогою параметра /L. У противному випадку параметр /N не приводить до якихось дій.

Приклад:

TASM /L /N TEST1


Параметр /P

Функція: Перевіряє наявність "некоректного" коду в захищеному режимі.

Синтаксис: /P

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

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

Приклад:


TASM /P TEST1


де TEST1 містить наступні операторы:


.286P

CODE SEGMENT

temp DW ?

mov CS:temp,0 ; у захищеному режимі може выполняться некоректно


Параметр Q

Функція: Придушує запису .OBJ, що не вимагаються при компоновке.

Синтаксис: /Q

Примітка: Даний параметр видаляє з одержуваного в результаті файлу (файлів) .OBJ запису про авторські права і залежність файлів. Цей параметр не слід вказувати, якщо ви використовуєте утиліту MAKE чи аналогічні програми, що при роботі учитывают ці записи.

Параметр /R

Функція: Генерує реальні інструкції з крапкою, що плаває.

Синтаксис: /R

Примітки: Параметр /R вказує Турбо Асемблеру, що потрібно генерувати реальні інструкції з крапкою, що плаває, (замість генерації емуляційних інструкцій із крапкою, що плаває,). Використовуйте цей параметр, якщо ви хочете виконувати свою програму на машинах, оснащеній арифметичним співпроцесором 80х87.

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

Якщо у вихідному файлі ви використовуєте директиву EMUL, то вона скасує дія інструкції /R, зазначеної в командному рядку.

Параметр командного рядка /R має той же ефект, що і використовування на початку вихідного файлу директиви NOEMUL і збігається з дією параметра командного рядка /JNOEMUL.

Приклад:


TASM /R SEGANT

TPC /$N+ /$E- TRIG.PAS


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

Параметр /S

Функція: Задає послідовне впорядкування сегментів.

Синтаксис: /S

Примітки: Параметр /S вказує Турбо Асемблеру, що сегменти в об'єктному файлі потрібно розмістити в тому порядку, у якому Турбо Асемблер виявляє їх у вихідному коді. За замовчуванням Турбо Асемблер використовує саме таке упорядочивание сегментів, якщо ви не змінили його за допомогою параметра /A у командному рядку чи у файлі конфігурації.

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

Приклад:


TASM /S TEST1


По даній команді створюється об'єктний файл (TEST1.OBJ), сегменты якого упорядковані в тім порядку, як вони містяться в вихідному файлі.

Параметр /T

Функція: Придушує виведення повідомлень при умовному асемблювання.

Синтаксис: /T

Примітки: Параметр /T придушує усю виведену Турбо Ассемблеру на екран інформацію, крім попереджень і повідомлень про помилки, що виникають у результаті асемблювання.

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

Приклад:


TASM /T TEST1


Параметр /V

Синтаксис: /V

Примітки: Параметр /V використовується з метою сумісності. Він не приводить ні до яких дій і не робить впливу на ассемблирование.

Параметр /W

Функція: Керує генерацією попереджуючих повідомлень.

Синтаксис: /W

W-[клас попереджень]

W+[клас попереджень]

Примітки: Параметр /W керує висновком Турбо Асемблером поперед- жуючих повідомлень.

Якщо ви просто вкажете параметр /W, то будуть виводитися "слабкі" попередження. Такі попередження показують, що ви можете трохи поліп- шити ефективність вашої програми.

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

ASS - мається на увазі використання 16-розрядного сегмента;

BRK - вимагаються квадратні дужки;

ICG - неефективна генерація коду;

LCO - переповнення лічильника адреси;

OPI - відкритий блок умови IF;

OPP - відкрита процедура;

OPS - відкритий сегмент;

OVF - арифметичне переповнення;

PDC - конструкція, що залежить від проходу;

PRO - запис у пам'ять у захищеному режимі вимагає перевизначення регістра CS;

RES - слово зарезервоване;

TPI - неприпустимо для Турбо Паскаля.

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

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

Для керування висновком визначених повідомлень на заданому ділянці програми у файлі з вихідним кодом ви можете використовувати директиви WARN чи NOWARN. Більш докладно про ці директиви распозначається в Главі 3 "Довідкового посібника".

Приклад:


TASM /W TEST1


Наступний оператор у програмі TEST1.ASM виведе попереджуюче повідомлення про те, що не з'явиться на екрані, якщо не зазначений параметр /W:


mov bx,ABC; попередження про неефективність коду

ABC = 1


При завданні командного рядка:


TASM /W-OVF TEST2


якщо файл TEST2.ASM містить директиву:


DW 1000h = 20h


попередження генеруватися не будуть.

Параметр /X

Функція: Включає в лістинг блоки умовного асемблирования.

Синтаксис: /X

Примітки: Якщо при обчисленні блоків IF, IFNDEF, IFDEF і т.д. виходить значення FALSE, те параметр /X приводить до тому, що оператори, що містяться усередині умовного блоку, будуть включены в лістинг асемблирования. по даній директиві в лістинг будуть також включені самі директиви умовного асемблирования (звичайно вони в лістинг не включаються).

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

Приклад:


TASM /X TEST1


Параметр /Z

Функція: Виводить на екран поряд з повідомленнями про помилку з-ответствующие рядка вихідного тексту.

Синтаксис: /Z

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

Приклад:


TASM /Z TEST1


Параметр /ZD

Функція: Дозволяє включення в об'єктні файли інформації про номерах рядків.

Синтаксис: /ZD

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

Приклад:


TASM /ZD TEST1


Параметр /ZI

Функція: Дозволяє включення в об'єктний файл інформації для налагодже- ння.

Синтаксис: /ZI

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

Приклад:


TASM /ZI TEST1


Непрямі командні файли

У будь-який момент, коли ви вводите командний рядок, Турбо Ассемблер дозволяє вам задавати непрямий командний файл, з по-міццю вказівки перед його ім'ям символу @. Наприклад:


TASM /DTESTMODE @MYPROJ.TA


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


TASM @MYFILES @IOLIBS /DBUF=1024


У такий спосіб ви можете використовувати довгий список стандартных файлів і параметрів, завдяки чому можна легко змінювати поведення Асемблера при кожнім асемблировании.

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

3 Відлагоджувальник td та прогін програми.

4 Основні команди пересилання даних.


Лекція 7


Прапорці операцій та команди порівняння

Створення розгалуження

Циклічні конструкції. Використання регістру CX для організації лічильного циклу

Реентерні та рекурсивні підпрограми. Математичні команди


Прапорці операцій та команди порівняння


ФЛАГОВИЙ РЕГІСТР

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

Номер біта: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Прапор: * * * * O D I T S Z * A * P * C

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

CF (Carry Flag) - прапор переносу. Містить значення "переносів" (0 чи 1) зі старшого розряду при арифметичес ких операціях і деяких операціях зрушення і циклічного зрушення (див. гл.12).

PF (Parity Flag) - прапор парності. Перевіряє молодші вісім біт результат- тов операцій над даними. Непарне число біт приводить до установки цього прапора в 0, а парне - у 1. Не варто плутати прапор парності з бітом контро- лю на парність.

AF (Auxiliary Carry Flag) - додатковий прапор переносу. Встановлюється в 1, якщо арифметична операція приводить до переносу четвертого праворуч біта (біт номер 3) у регистро виття однобайтовой команді. Даний прапор має відношення до арифметичних операцій над символами коду ASCII і до десяткових упакованим полям.

ZF (Zero Flag) - прапор нуля. Встановлюється в якості результату aрифметичних команд і команд порівняння. Як це не дивно, ненульовий результат приводить до установки нульового значення цього прапора, а нульовий - до установки одиничного значення. Існуюча невідповідність є, однак, логічно правильною, тому що 0 позначає "ні" (т.е. результат не дорівнює нулю), а одиниця позначає "так" (т.е. результат дорівнює нулю). Команди умовного переходу JE і JZ перевіряють цей прапор. SF (SIgn Flag) - знаковий прапор. Встановлюється у відповідності зі знаком результату (старшого біта) після арифметичних опеpацій: позитивний результат установлює 0, а негативний - 1. Команди умовного переходу JG і JL перевіряють цей прапор.

TF (Trap Flag) - прапор покрокового виконання. Цей прапор вам уже прихо- дилося встановлювати, коли використовувалася до манда Т в отладчике DEBUG. Якщо цей прапор встановлений в единичное cостояние, те процесор переходить у режим покрокового виконання команд, тобто в кожен момент виконується одна команда під користувальницьким керуванням.

IF (Interrupt Flag) - прапор переривання. При нульовому складаючись нии цього прапора переривання заборонені, при одиничному - дозволені.

DF (DIrection Flag) - прапор напрямку. Використовується в строкових опера- ціях для визначення напрямку передачі даних. При нульовому стані команда збільшує вміст регістрів SI і DI, викликаючи передачу даних ліворуч праворуч, при нульовому - зменшує вміст цих регістрів, викликаючи передачу даних праворуч ліворуч (див. гл.11).

OF (Overflow Flag) - прапор переповнення. Фіксує арифметическое переповнення, тобто перенос в/из старшого (знакового) біта при знакових арифметичних операціях. Як приклад: команда CMP порівнює два операнда

і воздействуте на прапори AF, CF, OF, PF, SF, ZF. Однак, немає необхідності перевіряти всі ці прапори по окремості. У сле- прикладі, що дує, перевіряється чи містить регістр BX нульове значення:


CMP BX,00 ;Порівняння BX з нулем

JZ B50; Перехід на B50 якщо нуль. (дії при ненулі)

B50: ... ;Крапка переходу при BX=0


Якщо BX містить нульове значення, команда CMP установлює прапор нуля ZF в одиничний стан, і можливо змінює (чи немає) інші прапори. Команда JZ (перехлд якщо нуль) перевіряє тільки прапор ZF. При одиничному значенні ZF, що позначає нульова ознака, команда передає керування на адресу, зазначений у її операнде, тобто на мітку B50.

Команда порівняння

Команда порівняння CMP порівнює два числа, віднімаючи одне з іншого. Вона не записує результат, але прапори стану установлює відповідно до результату. Ця команда змінює тільки прапори. У програмі команда порівняння використовується так само, як і команда вирахування; однак команди порівняння з заемом не існує. Порівняння з підвищеною точністю вимагає ледве більше зусиль, чим порівняння чи байтів слів. Фактично в цих випадках багато простіше використовувати команду вирахування замість команди порівняння. На рис.П4.11 показане порівняння пари 32=бітових чисел у пам'яті з використанням регістра AX у якості області тимчасового збереження. Це порівняння визначає, яке з чисел більше. Програма в результаті свого виконання встановлює коди умови. Прапор переносу визначає, яке з чисел більше: якщо прапор дорівнює 1, число VALUE більше.

Програма перевіряє два 32=бітових числа на рівність. Програма зберігає молодший результат, а потім комбінує його зі старшим, і в такий спосіб з'ясовує еквівалентність результату нулю. Команда OR описана в наступному розділі, а тут істотно те, що вона комбінує два значення так, що остаточне значення дорівнює 0 тоді і тільки тоді, коли обоє вихідних значення рівні 0. Результат цієї підпрограми порівняння - значення прапора нуля; якщо він дорівнює 1, числа рівні.


2. Створення розгалуження


Розглядаючи призначення команд умовного переходу випливає пояснити характер їхнього використання. Типи даних, над якими виконуються арифметичні операції й операції порівняння визначають якими командами користатися: беззнаковими чи знаковими. Беззнакові дані використовують усі біти як біти даних; характерним прикладом є символьні рядки: імена, адреси і натуральні числа. У знакових даних самий лівий біт являє собою знак, причому якщо його значення дорівнює нулю, то число позитивне, і якщо одиниці, те негативне. Багато числових значень можуть бути як позитивними так і негативними. Як приклад припустимо, що регістр AX містить 11000110, а BX - 00010110. Команда CMP AX,BX порівнює вміст регістрів AX і BX. Якщо дані беззнакові, то значення в AX більше, а якщо знакові - те менше. Переходи для беззнакових даних.


Мова програмування Assembler


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

Переходи для знакових даних


Мова програмування Assembler


Команди переходу для умови дорівнює чи нуль (JE/JZ) і не дорівнює чи не нуль (JNE/JNZ) присутні в обох списках для беззнакових і знакових даних. Стан дорівнює/нуль відбувається поза залежністю від наявності знака.

Специальные арифметические проверки


Мова програмування Assembler


Ще одна команда умовного переходу перевіряє чи дорівнює вміст регістра CX нулю. Ця команда необов'язково повинна pасполагаться безпосередньо за командою арифметики чи порівняння. Одним з місць для команди JCXZ може бути початок циклу, де вона перевіряє чи містить регістр CX ненульове значення. Не поспішаєте поки заучувати ці команди напам'ять. Запам'ятаєте тільки, що для беззнакових даних є переходи по складаючись ниям дорівнює, чи вище нижче, а для беззнакових - дорівнює, чи більше менше. Переходи по перевірках прапорів переносу, переповнення і паритету мають особливе призначення. Асемблер транслює мнемонічні коди в об'єктний код незалежно від того, яку з двох команд ви застосували. Однак, команди JAE і JGE будучи явно однаковими, перевіряють різні прапори.


3. Циклічні конструкції. Використання регістру CX для організації лічильного циклу


Але більш ймовірно підпрограма повинна виконувати визначене число циклів. Команда LOOP, що служить для цієї мети, використовує початкове значення в регістрі CX. У кожнім циклі команда LOOP автоматично зменшує вміст регістра CX на 1. Поки значення в CX не дорівнює нулю, керування передається за адресою, зазначеному в операнде, і якщо в CX буде 0, керування переходить на слудующую після LOOP команду. Програма на рис. 7.2, що ілюструє використання команди LOOP, виконує дії, аналогічні прикладу на рис. 7.1 за винятком того, що після десяти циклів програма завершується. Команда MOV инициализирует регістр CX значенням 10. Оскільки команда LOOP використовує регістр CX, то в програмі для подвоєння початкового значення 1 замість регістра CX використовується DX. Команда JMP A20 замінена командою LOOP і для ефективності команда ADD AX,01 замінена командою INC AX (збільшення AX на 1). Аналогічно команді JMP, операнд команди LOOP визначає відстань від кінця команди LOOP до адреси мітки A20, которої додається до вмісту командного покажчика. Для команди LOOP ця відстань повинна бути в межах від -128 до +127 байт. Якщо операнд перевищує ці границі, то ассемблер видасть повідомлення "Relative jump out of range" (перевищені границі переходу). Для перевірки команди LOOP рекомендується змінити відповідним чином програму, приведену на рис.7.1, виконати її асемблювання, компоновку і перетворення в COM-файл. Для трасування всіх десяти циклів використовуйте налагоджувач DEBUG. Коли в значення регістрі CX зменшиться до нуля, вміст регістpів AX, BX і DX буде відповідно тичина. 000B, 0042 і 0400. Для виходу з відлагоджувача введіть команду Q. Додатково існує два різновиди команди LOOP - це LOOPE (чи LOOPZ) і LOOPNE (чи LOOPNZ). Обидві команди також зменшують значення регістра CX на 1. Команда LOOPE передає керування за адресою операнда, якщо регістр CX має ненульове значення і прапор нуля встановлений (ZF=1). Команда LOOPNE передає керування за адресою операнда, якщо регістр CX має ненульове значення і прапор нуля скинутий (ZF=0).


4. Реентерні та рекурсивні підпрограми. Математичні команди


КОМАНДИ ЛОГІЧНИХ ОПЕРАЦІЙ: AND, OR, XOR, TEST, NOT

Логічні операції є важливим елементом у проектуванні мікросхем і мають багато загального в логіку програмування. Команди AND, OR, XOR і TEST - є командами логічних операцій. Ці команди використовуються для скидання й установки біт і для арифметичних операцій у коді ASCII (див.гл.13). Усі ці команди обробляють один байт або одне слово в регістрі або в пам'яті, і встановлюють прапори CF, OF, PF, SF, ZF.

AND: Якщо обоє з порівнюваних бітів рівні 1, то результат дорівнює 1; у всіх інших випадках результат - 0.

OR: Якщо хоча б один з порівнюваних бітів дорівнює 1, то результат дорівнює 1; якщо порівнювані біти рівні 0, то результат - 0.

XOR: Якщо один з порівнюваних бітів дорівнює 0, а іншої дорівнює 1, то результат дорівнює 1; якщо порівнювані біти однакові (обоє - 0 чи обоє - 1) то результат - 0.

TEST: діє як AND-встановлює прапори, але не змінює біти.

Перший операнд у логічних командах вказує на один байт або слово в регістрі або в пам'яті і є єдиним значенням, що може змінюватися після виконання команд.У наступних командах AND,OR і XOR використовуються однакові бітові значення:


AND OR XOR

0101 0101 0101

0011 0011 0011

Результат: 0001 0111 0110


Для наступних незв'язаних прикладів, припустимо, що AL містить 1100 0101, а BH містить 0101 1100:


1. AND AL,BH ;Встановлює в AL 0100 0100

2. OR BH,AL ;Встановлює в BH 1101 1101

3. XOR AL,AL ;Встановлює в AL 0000 0000

4. AND AL,00 ;Встановлює в AL 0000 0000

5. AND AL,0FH ;Встановлює в AL 0000 0101

6. OR CL,CL ;Установлює прапори SF і ZF


Приклади 3 і 4 демонструють спосіб очищення регістра. У прикладі 5 обнуляются ліві чотири біти регістра AL. Хоча команди порівняння CMP можуть бути зрозуміліше, можна застосувати команду OR для наступних цілей:


1. OR CX,CX ;Перевірка CX на нуль

JZ ;Перехід, якщо нуль

2. OR CX,CX ;Перевірка знака в CX

JS ... ;Перехід, якщо негативно


Команда TEST діє аналогічно команді AND, але встановлює тільки прапори, а операнд не змінюється. Нижче наведемо кілька прикладів:


1. TEST BL,11110000B ;Любою з лівих біт у BL

JNZ ... ; дорівнює одиниці?

2. TEST AL,00000001B ;Регістр AL містить

JNZ ... ; непарне значення?

3. TEST DX,OFFH ;Регістр DX містить

JZ ... ; нульове значення?


Ще одна логічна команда NOT встановлює обернене значення біт у чи байті в слові, у чи регістрі в пам'яті: нулі стають одиницями, а одиниці - нулями. Якщо, наприклад, pегістр AL містить 1100 0101, то команда NOT AL змінює це значення на 0011 1010. Прапори не міняються. Команда NOT не еквівалентна команді NEG, що змінює значення з позитивного на нега- тивне і навпаки, за допомогою заміни біт на протилежне значення і додатки одиниці (см."Негативні числа" у гл.1.).

КОМАНДИ ЗРУШЕННЯ І ЦИКЛІЧНОГО ЗРУШЕННЯ

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

- обробляють чи байт слово;

- мають доступ до чи регістра до пам'яті;

- зрушують чи уліво вправо;

- зрушують на величину до 8 біт (для байта) і 16 біт (для слова);

- зрушують логічно (без знака) чи арифметично (з знаком).

Значення зрушення на 1 може бути закодоване як непосред cтвенный операнд, значення більше 1 повинне знаходитися в регістрі CL.

Команди зрушення

При виконанні команд зрушення прапор CF завжди містить значення останнього висунутого біта. Існують наступні команди cдвига:

SHR ;Логічний (беззнаковий) зрушення вправо

SHL ;Логічний (беззнаковий) зрушення вліво

SAR ;Арифметичне зрушення вправо

SAL ;Арифметичне зрушення вліво

Наступний фрагмент ілюструє виконання команди SHR:


MOV CL,03 ; AX:

MOV AX,10110111B ; 10110111

SHR AX,1 ; 01011011 ;Зрушення вправо на 1

SHR AX,CL ; 00001011 ;Зрушення вправо на 3


Перша команда SHR зрушує вміст регістра AX вправо на 1 біт. Висунутий у результаті один біт попадає в прапор CF, а самий лівий біт регістра AX заповнюється нулем. Друга команда зсуває вміст регістра AX ще на три біти. При цьому прапор CF послідовно приймає значення 1, 1, 0, а в три лівих біти в регістрі AX заносяться нулі. Розглянемо дію команд арифметичного вправо SAR:


MOV CL,03 ; AX:

MOV AX,10110111B ; 10110111

SAR AX,1 ; 11011011 ;Зрушення вправо на 1

SAR AX,CL ; 11111011 ;Зрушення вправо на 3


Команда SAR має важливу відмінність від команди SHR: для заповнення лівого біта використовується знаковий біт. Таким чином, позитивні і негативні величини зберігають свій знак. У приведеному прикладі знаковий біт містить одиницю. При зрушеннях уліво праві біти заповнюються нулями. Таким чином, результат команд зрушення SHL і SAL ідентичний. Зрушення вліво часто використовується для подвоєния чисел, а зрушення вправо - для розподілу на 2. Ці операції здійснюються значно швидше, ніж команди чи множення розподілу. Розподіл навпіл непарних чисел (наприклад, 5 чи 7) утворить менші значення (2 чи 3, відповідно) і встановлює прапор CF у 1. Крім того, якщо необхідно виконати зрушення на 2 біти, то використання двох команд зрушення більш эффективніше, ніж використання однієї команди з завантаженням регістра CL значенням 2. Для перевірки біта, занесеного в прапор CF використовується команда JC (перехід, якщо є перенос).

Команди циклічного зрушення

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

ROR ;Циклічне зрушення вправо

ROL ;Циклічне зрушення вліво

RCR ;Циклічне зрушення вправо з переносом

RCL ;Циклічне зрушення вліво з переносом

Наступна послідовність команд ілюструє операцію циклічного зрушення ROR: MOV CL,03 ; BX:


MOV BX,10110111B ; 10110111

ROR BX,1 ; 11011011 ;Зрушення вправо на 1

ROR BX,CL ; 01111011 ;Зрушення вправо на 3


Перша команда ROR при виконанні циклічного зрушення переносить правий одиничний біт регістра BX у ліву позицію, що звільнилася . Друга команда ROR переносить у такий спосіб три правих біти. У командах RCR і RCL у зрушенні бере участь прапор CF. Висуваємий з регістра біт заноситься в прапор CF, а значення CF при цьому надходить у позицію, що звільнилася. Розглянемо приклад, у якому використовуються команди циклічного і простого зрушення. Припустимо, що 32-бітове значення знахо- диться в регістрах DX:AX так, що ліві 16 біт лежать у регістрі DX, а праві - у AX. Для множення на 2 цього значення можливі cлідуючі дві команди:


SHL AX,1 ;Множення пари регістрів

RCL DX,1 ; DX:AX на 2


Тут команда SHL зсуває всі біти регістра AX вліво, причому самий лівий біт попадає в прапор CF. Потім команда RCL зсуває всі біти регістра DX вліво і у правий біт, що звільнився, заносить значення з прапора CF. Арифметичні команди будь-якого мікропроцесора залучають до себе найбільше уваги. Кожний зацікавлений у виконанні арифметичних обчислень, і саме ці команди проробляють таку роботу. Хоча їх небагато, вони виконують більшість перетворень, даних у мікропроцесорі. У реальних же умовах, арифметичні команди займають лише малу частину усіх команд, що виконуються. Команди пересилання використовують більшість принципів роботи команд мікропроцесора 8088, а при вивченні арифметичних команд необхідно розглянути деякі тонкості їх виконання.

Команда додавання

Команда ADD виконує додавання зазначених операндів, представлених у двійковому доповняльному коді. Мікропроцесор поміщає результат на місце першого операнда після того, як складе обох операндів. Другий операнд не змінюється. Команда коректує регістр прапорів у відповід- ності з результатом додавання. Наприклад, команда ADD AX, BX складає вміст регістра BX із вмістом регістра AX, і залишає результат у регістрі AX. Регістр прапорів повідомляє про те, чи був результат нульовим, негативним, чи мав парність, або перенос переповнення. Малюнок 4.8 коротко ілюструє варіанти команди ADD. Існують дві форми додавання, 8=бітове і 16=бітове. У різних формах додавання беруть участь різні регістри. Асемблер стежить за тим, щоб операнди відповідали один одному. Вміст байтового регістра (наприклад, CH) не може бути доданим до комірки пам'яті, яка не має тип BYTE. Якщо комірка пам'яті є одним з операндів, вона може бути або операндом - результатом, або незмінним операндом. Тим самим команда може додати вміст регістра до комірки пам'яті і повернути результат у пам'ять. Одним з операндів може також бути безпосереднє значення. На рис. П4.9 показаний лістинг асемблера з деякими арифметичними командами.

Команда додавання з переносом ADC - це та ж команда ADD, за винятком того, що в суму включається прапор переносу. Для будь-якої форми команди ADD існує порівнювана з нею команда ADC. Обидві команди додавання, як ADD, так і ADC, установлюють рівним 1 прапор переносу, якщо відбувся перенос зі старшого розряду результату. Команда ADD складає два операнда, не звертаючи уваги на прапор переносу, а команда ADC враховує і прапор переносу. Якщо прапор переносу дорівнює 0, результат дорівнює результату виконання команди ADD. Якщо ж прапор переносу дорівнює 1, то результат на 1 більше результату команди ADD. Таким чином, програма може використовувати прапор переносу для операцій підвищеної точності. Малюнок П4.10 ілюструє додавання пари 32=бітових чисел; у прикладі складаються 32-бітові числа поля VALUE1 і поля VALUE2, а результат міститься в полі VALUE2. Помітимо, що один з операндів повинен бути поміщений у регістр. У першому додаванні використовується команда ADD, тому що поточне значення прапора переносу несуттєве для першого додавання. Після відповідного розміщення операндів програма на рис.П4.10 виконує друге додавання за допомогою команди ADC, з урахуванням прапора переносу, встановленого попереднім додаванням. Це також гарний приклад що показує, чому команда MOV не встановлює ніяких прапорів. Якби команда MOV змінювала прапори, виконати правильно друге додавання було б набагато складніше.

Команда вирахування

Команди вирахування SUB і SBB ідентичні командам додавання, за винятком того, що вони виконують вирахування, а не додавання. Ви можете скорегувати рис.4.8 для розрахування, змінивши знак "+" на знак "-". Розрахунок встановлює прапори стану відповідно до результату операції, причому прапор переносу тепер означає позика. Наприклад, команда SUB AX, BX віднімає значення регістра BX зі значення регістра AX, а потім поміщає результат у регістр AX. Прапори стану змінюються так, щоб відбивати результат виконання команди. Команда розрахування з заемом SBB вирішує задачі розрахування підвищеної точності. Команда SBB враховує прапор заема при розрахуванні, тобто значення заема віднімається з результату, отриманого при нормальному розрахуванні. На рис.П4.10 показано розрахування підвищеної точності, виконане з тими ж значеннями, що і додавання. У цьому прикладі значення поля VALUE1 віднімається зі значення поля VALUE2, поміщаючи результат у поле VALUE2.

Арифметика з одним операндом

Команда заперечення NEG - це оператор зміни знака. Вона змінює знак двоичного додаткового коду операнда - байта чи слова. Інші дві команди з одним операндом змінюють значення оперенда на 1. Команда збільшення INC додає 1 до операнду, а команда зменшення DEC віднімає 1 з операнда.За допомогою команд збільшення і зменшення можна переміщати покажчик по масиві комірок пам'яті. Ці команди також можуть реалізувати лічильник циклу. Кожен прохід по циклу зменшує лічильник, а коли його значення досягне 0, цикл завершується. Усі ці однооперандні команди можуть мати в якості операнда як байт, так і слово. Якщо кожна з цих команд вказує комірку пам'яті за допомогою одного з непрямих способів адресації, наприклад [BX+SI], асемблер має потребу в допомозі, тому що йому необхідно знати довжину операнда в пам'яті, щоб породити правильний код операції. Команда може використовувати модифікатори BYTE PTR чи WORD PTR, щоб описати операнд.

Ці три команди впливають на регістр стану точно так само, як це роблять арифметичні команди. Додаток 1, вирахування 1 і вирахування з 0 ідентичні відповідно INC, DEC і NEG; однак команди з одним операндом більш ефективні.


Лекція 8


Поняття "переривання"

Поділ переривань між BIOS та операційною системою

Використання переривань у програмах

Основні переривання та їх функції (крім 21h)


1. Поняття "переривання"


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

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

ПЕРЕРИВАННЯ

Інструкція INT активізує процедуру, передбачену для обробки переривання з зазначеним номером. Покажчик стека SP зменшується на 2, у стек містяться прапори (у форматі інструкції PUSHF) і прапори TF і IF устанавливаютя в 0 (для заборони покрокового режиму і маскируемых переривань). Потім SP зменшується ще на 2, і в стек заноситься вміст регістра CS. Адреса покажчика переривання (тобто місцезнаходження адреси програми обробки переривання) обчислюється шляхом множення зазначеного в інструкції INT номера на 4: друге слово покажчика заміщає значення регістра CS. SP знову зменшується на 2, і в стек міститься

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

ПЕРЕРИВАННЯ, ЯКЩО Є ПЕРЕПОВНЕННЯ

По інструкції INTO генерується програмне переривання, якщо встановлений у 1 прапор OF; у противному випадку керування передається наступної інструкції без активізації процедури обробки переривання. Інструкція INTO звертається до необхідній процедурі (номер переривання - 4) через покажчик переривання, розташований по 16-ричному адресі 10, встановлює в 0 прапори TF і IF і в іншому працює також, як INT. Інструкція INTO може використовуватися після арифметичних чи логічних операцій для обробки можливих переповнень.

КРАПКА ВИХОДУ

Виконання цієї інструкції еквівалентно перериванню з номером 3 ("досягнута крапка виходу"). Асемблер генерує коротку, 1-байтную машинну інструкцію.

ПОВЕРНЕННЯ З ПЕРЕРИВАННЯ

По інструкції IRET керування повертається в крапку переривання шляхом відновлення зі стека вмісту регістрів IP і CS і значень прапорів, поміщених туди при виникненні переривання. Ця інструкція використовується для виходу як із програмних, так і з апаратних переривань.

2. Поділ переривань між BIOS та операційною системою


У даному розділі представлені основні переривання BIOS. INT 05H (Печатка екрана). Приводить до передачі вмісту екрана на друкувальний пристрій. INT 05H застосовується для внутрішніх цілей, тобто з програм, клавіші Ctrl/PrtSc активізують печатка з клавіатури. Дана операція маскує перери- вання і зберігає позицію курсору.


Мова програмування Assembler

Примітка: Переривання 00-1F відносяться до BIOS, переривання 20-FF відносяться до DOS і BASIC.

ПЕРЕРИВАННЯ BIOS

У даному розділі приведені основні переривання BIOS. INT 05H Печатка екрана. Виконує виведення вмісту екрана на друкувальний пристрій. Команда INT 05H виконує дану операцію з програми, а натискання клавішею Ctrl/PrtSc - з клавіатури. Операція забороняє переривання і зберігає позицію курсору. INT 10H Керування дисплеєм. Забезпечує екранні і клавіатурні операції, детально описані в главі 9. INT 11H Запит списку приєднаного устаткування. Визначає наявність різних пристроїв у системі, що результують значення і повертає в регістр AX. При включенні комп'ютера система виконує цю операцію і зберігає вміст AX у пам'яті за адресою тичина.410. Значення бітів у регістрі AX:


Мова програмування Assembler


INT 12H Запит розміру фізичної пам'яті. Повертає в регістрі AX розмір пам'яті в кілобайтах, наприклад, тичина.200 відповідає пам'яті в 512 ДО. Дана операція корисна для вирівнювання розміру програми відповідно до доступного пам'яттю.

INT 13H Дискові операції введення-висновку. Забезпечує операції введення-висновку для дискет і вінчестера, розглянуті в главі 16.

INT 14H Керування комунікаційним адаптером. Забезпечує послідовний введення-виведення через комунікаційний порт RS232. Регістр DX повинний містити номер (0 чи 1) адаптера стику RS232. Чотири типи операції, обумовлені регістром AH, виконують прийом і передачу символів і повертають у регістрі AX байт стану комунікаційного порту.

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

INT 16H Уведення з клавіатури. Забезпечує три типи команд уведення з клавіатури, докладно описані в главі 9.

INT 17H Виведення на принтер. Забезпечує виведення даних на друкуючий пристрій. Докладно розглянуто в главі 19.

INT 18H Звертання до BASIC, убудованому в ROM. Викликає BASIC-інтер- претатор, що знаходиться в постійній пам'яті ROM.

INT 19H Перезапуск системи. Дана операція при доступному диску зчитує сектор 1 з доріжки 0 в область початкової завантаження в пам'яті (сегмент 0, зсув 7C00) і передає керування по цій адресі. Якщо дисковод не доступний, то операція передає керування через INT 18H у ROM BASIC. Дана операція не очищає екран і не інніціалізує дані у ROM BASIC, тому її можна використовувати з програми.

INT 1AH Запит і установка поточного часу і дати. Зчитує і записує показання годин у відповідності із значенням у регістрі AH. Для визначення тривалості виконання програми можна перед початком виконання установити годинник у 0, а після вважати поточний час. Відлік часу йде приблизно 18,2 рази в секунду. Значення в регістрі AH відповідає наступним операціям:

AH=00 - Запит часу. У регістрі CX установлюється старийшая частина значення, а в регістрі DX - молодша. Якщо після останнього запиту пройшло 24 години, то в регістрі AL буде не нульове значення.

AH=01 - Установка часу. Час установлюється по регістрам CX (старша частина значення) і DX (молодша частина значення).

Коди 02 і 06 керують часом і датою для AT.

INT 1FH Адреса таблиці графічних символів. У графічному режимі існує доступ до символів з кодами 128-255 у 1ДО таблиці, що містить по вісім байт на кожен символ. Прямий доступ у графічному режимі забезпечується тільки до перших 128 ASCII-символів (від 0 до 127).

ПЕРЕРИВАННЯ DOS

Під час своєї роботи BIOS використовує два модулі DOS: IBMBIO.COM і IBMDOS.COM. Оскільки модулі DOS забезпечують велику кількість різних додаткових перевірок, то операція DOS звичайно простіша у використан- ні і менш машинно залежна, чим їх BIOS аналоги.

Модуль IBMBIO.COM забезпечує інтерфейс із BIOS низького рівня. Ця програма виконує керування введенням-висновком при читанні даних із зовнішніх пристроїв у пам'ять і записи з пам'яті на зовнішні пристрої.

Модуль IBMDOS.COM містить засоби керування файлами і ряд сервісних функцій, таких як блокування і деблокування записів. Коли користуваль- ницька програма видає запит INT 21H, то в програму IBMDOS через регістри передається визначена інформація. Потім програма IBMDOS транслює цю інформацію в один чи декілька викликів IBMBIO, що в свою чергу викликає BIOS. Зазначені зв'язки приведені на наступній схемі:

Користувальницький Вищий Нижчий ROM Зовнішній


Мова програмування Assembler


Як показано вище, переривання від тичина 20 до тичина 62 зарезервовані для операцій DOS. Нижче приведені найбільш основні з них:

INT 20H Завершення програми. Запит завершує виконання програми і передає керування в DOS. Даний запит звичайно знаходиться в основній процедурі.

INT 21H Запит функцій DOS. Основна операція DOS, яка визиває визначену функцію відповідно до коду в регістрі AH. Призначення функцій DOS описано в наступному розділі.

INT 22H Адреса підпрограми обробки завершення задачі. (см.INT 24H).

INT 23H Адреса підпрограми реакції на Ctrl/Break. (см.INT 24H).

INT 24H Адреса підпрограми реакції на фатальну помилку. У цьому елементі й у двох попередніх містяться адреси, які ініціалізуються системою в префіксі програмного сегмента і, які можна змінити для своїх цілей. Подробиці приведені в технічному описі DOS.

INT 25H Абсолютне читання з диска. Див.гл.17.

INT 26H Абсолютний запис на диск. Див.гл.17.

INT 27H Завершення програми, що залишає її резедентною.

Дозволяє зберегти COM-програму в пам'яті. Докладно дана операція показана в наступному розділі "Резидентні програми".


3. Використання переривань у програмах


Засобу ініціювання й обробки переривань є важливою складовою частиною будь-якої обчислювальної системи, в тому числі і персональної ЕОМ. Механізм переривань забезпечує ефективна взаємодія пристроїв уведення-висновку з мікропроцесором. Переривання цікавлять нас тому, що обробка переривань - це прерогатива програмування на мові асемблера. У високорівневих мовах відсутні засоби роботи з перериваннями на машинному рівні. Переривання звичайно викликаються зовнішніми пристроями. Переривання сигналізує мікропроцесору, щоб він призупинив виконання поточного завдання і приділив увагу зовнішньому пристрою. У IBM PC клавіатура посилає сигнал переривання кожного раз, коли натискається одна з клавіш. Це переривання повідомляє мікропроцесору, що потрібно припинити поточну роботу і вважати символ із клавіатури. Неважко зрозуміти походження терміна "переривання": сигнал переривання "перериває" поточну роботу мікропроцесора. Переривання є гарним поміч- ником для мікропроцесора, оскільки звільняє його від постійного контролю за зовнішніми пристроями. Якби, наприклад, клавіатура не викликала переривання, то мікропроцесору приходилося б постійно перевіряти стан клавіатури, щоб визначити, чи не була натиснута якась із клавіш. Будь-яка написана для ЕОМ програма повинна була б містити ту саму процедуру, і у процесі свого виконання досить часто здійснювати перевірку стану клавіатури. Однак наявність переривання, знімає це обмеження, і програма може виконуватися без такої перевірки. Клавіатура сигналізує мікропроцесору, щораз, коли їй треба передати інформацію мікропроцесору. Після того, як мікропроцесор задовільнить запит клавіатури, він може відновити нормальний хід виконання програми. У мікропроцесорі 8088 обробка переривань багато в чому схожа на виконання підпрограм. Якщо виникає переривання, то воно не може зупинити мікропроцесор під час виконання ним команди. Насамперед мікропроцесор 8088 завершує виконання поточної команди. Потім, не звертаючи уваги на наступну команду програми, він діє як у випадку виклику підпрограми. Мікропроцесор записує адреса наступної команди в стек і переходить до спеціальної підпрограми, названою обробкою переривання. Ця підпрограма містить команди, що вимагаються пристроєм, який визиває переривання. Для клавіатури, в обробку переривання входять зчитування і запис символу в пам'ять для наступного його використання. Після того, як підпрограма обробки переривання закінчила роботу з пристроєм, він здійснює повернення в крапку програми, де відбулося переривання. Мікропроцесор зчитує зі стека адреса повернення, і програма продовжує виконуватися, начебто нічого не відбулося. Оскільки переривання викликається зовнішніми пристроями, воно може відбутися в будь-який момент виконання програми. Неможливо передбачити в програмі ніяких спеціальних мір підготовки до виникнення переривання, тому що для програми момент уведення символу з клавіатури оператором є непередбаченим. Звідси випливає, що підпрограма обробки переривання не повинна модифікувати значення дані, використо- вувані перерваною програмою. У випадку модифікації їх програма після повернення їй керування не зможе виконуватися правильно. Частина процедури переривання полягає в тому, що коли вона виникає, мікропроцесор 8088 автоматично записує в стек деякі дані перерваної програми. У свою чергу, підпрограма обробки переривань відповідає за запис у пам'ять будь-яких інших даних, що вона може змінити в час свого виконання. Звичайно ці дані записуються в стекову пам'ять. Потім, перед поверненням керування перерваній програмі, підпрограма обробки переривань повинна відновити програмні параметри відповідно до їх значення в момент переривання. Факт виникнення переривання не повинен відбитися на виконуваній програмі. Оскільки існує багато пристроїв, що посилають мікропроцесору сигнали переривання, у мікропроцесорі 8088 мається механізм переривання по вектору. Це означає, що мікропроцесор 8088 визначає, який з пристроїв запросив переривання, і передає керування потрібній програмі обробки переривань, що відповідає цьому пристрою. Мікропроцесор автоматично виконує векторизацію запитів на переривання. Програма обробки переривань не повинна перед обслуговуванням пристрою визначати, яке з них запросило переривання. Це зменшує тривалість переривання і спрощує програму його обробки. У програмах зустрічаються такі ділянки, виконання яких не може бути перервано. Можливо, що частина деякої конкретної програми повинна виконуватися дуже швидко для того, щоб одержати визначений результат, або програма працює з даними, що зберігалися у пам'яті, які можуть бути змінені при обробці переривань. У кожному з цих випадків програма повинна мати можливість заборонити переривання, тобто не допускати виконання переривання на цих критичних ділянках програми. Після прохо- дження цих ділянок, функціонування ситеми переривань повинне бути відновлено програмою. Програма не може блокувати систему переривань занадто довго, інакше в обслуговуванні пристрою, який запросив перерива- ння, може відбутися збій. Якщо програма обробки переривання, яке надійш- ло з клавіатури, не встигне обдумати символ перед тим, як оператор надрукує наступний, то цей другий символ може бути загублений. У мікропроцесорі 8088 є можливість увести заборону на всі зовнішні переривання. У IBM PC, крім того, є можливість задавати пристрою, що можуть викликати переривання. Це дозволяє вибрати в програмі найбільш важливі пристрої, яким дозволене переривання, і одночасно заборонити переривання від інших, менш важливих. Методи заборони переривань будуть розглянуті в наступних главах.


4. Основні переривання та їх функції (крім 21h)


Принтери класифікуються по якості друку. Матричний принтер формує символи у виді матриці крапок і забезпечує нормальний, вузький і широкий формати символів. Більш модернізовані матричні принтери забезпечують крапкову графіку, похилий шрифт, жирний друк і подвійну щільність, а також можуть друкувати, наприклад, символи гральних карт і інші алфавітно-цифрові символи. Високоякісні друкуючі пристрої, що тануть, обмежені набором символів на змінної "ромашці" чи барабані, але забезпечують відмінну якість друку і велику розмаїтість принтерів. Багато з високоякісних принтерів забезпечують друк в 10,12 чи 15 символів на дюйм, а також пропорційне розташування пробілів, підкреслення, тіньового і напівжирного друку. Лазерні принтери мають переваги як для матричної графіки, так і для якісного друку текстів. Інша класифікація друкувальних пристроїв зв'язана з інтерфейсами. Комп'ютери IBM PC мають рівнобіжний інтерфейс, що дозволяє передавати одночасно вісім бітів інформації на принтер. Крім того, існує послідовний інтерфейс, який виконує побітову передачу даних. Багато принтерів мають буфер пам'яті, обсягом у декілька тисяч байтів. Принтери також можуть приймати біти контролю на парність (непарність). Принтери повинні "розуміти" спеціальні сигнали з процесора, наприклад, для прогону листа, перекладу чи рядка горизонтальної табуляції. У свою чергу, процесор повинен "розуміти" сигнали від принте- ра, що вказують на кінець папера або стан "зайняте". На жаль багато типів принтерів по різному реагують на сигнали процесора й однією з найбільш складних проблем для програмістів - забезпечити відповідність власних програм наявним друкувальним пристроєм.

СИМВОЛИ КЕРУВАННЯ ПЕЧАТКОЮ

Стандартними символами керування печаткою є:


Мова програмування Assembler


Горизонтальна табуляція.

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

Переклад рядка.

Символ перекладу рядка (тичина.OA) використовується для прогону листа на один інтервал. Відповідно для друку через два інтервали використо-вується два символи перекладу рядка.

Прогін сторінки.

Установка паперу після включення принтера визначає початкову позицію друку сторінки. Довжина сторінки за замовчуванням складає 11 дюймів. Ні процесор, ні принтер автоматично не визначають кінець сторінки. Якщо ваша програма продовжує друкувати після закінчення сторінки, то відбу- деться перехід через міжсторінкову перфорацію на початок наступної сто- рінки. Для керування сторінками необхідно підраховувати число надрукова- них рядків і при досягненні максимального значення (наприклад, 55 рядків) видати код прогона сторінки (тичина.OC), а потім скинути лічильник рядків у 0 чи 1. Наприкінці друку необхідно видати символ "перекладу рядка" або "прогону сторінки" для видачі на друк даних останнього рядка, що знаходяться в буфері друкуючого пристрою. Використання останнього символу "прогін сторінки" дозволяє встановити надрукований останній лист у положення для відриву.

ФУНКЦІЇ ПЕЧАТКИ В РОЗШИРЕНІЙ ВЕРСІЇ DOS

В операційній системі DOS 2.0 наявні файлові покажчики, що були показані в главах по керуванню екраном дисплея і дискової печатки. Для висновку на друкуючий пристрій використовується функція DOS тичина.40 і стандартний файловий номер 04. Наступний приклад демонструє печатка 25 символів з області HEADG:


Мова програмування Assembler


У випадку помилки операція встановлює прапор CF і повертає код помилки в регістрі AX.

ПРОГРАМА: ПОСТОРІНКОВА ПЕЧАТКА З ЗАГОЛОВКАМИ

Програма, приведена на рис.19.1, аналогічна програмі на рис.9.1, за винятком того, що після введення імен з клавіатури виводить їх не на екран, а на друкуючий пристрій. Кожна надрукована сторінка містить заголовок, і через подвійний інтервал список введених імен у наступному виді:

List of Employee Names Page 01

Clancy Alderson

Ianet Brown

David Christie

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

D10INPT Видає на екран запит і потім вводить ім'я з клавиатури.

E10PRNT Виводить ім'я на друкуючий пристрій (довжина імені береться з вступного списку параметрів); у кінці сторінки викликає процедуру M10PAGE.

M10PAGE Виконує прогін на нову сторінку, друкує заголовок, скидає лічильник рядків і збільшує лічильник сторінок на одиницю.

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

На початку виконання необхідно надрукувати заголовок, але не робити перед цим переклад сторінки. Процедура M10PAGE обходить переклад сторінки, якщо лічильник PAGECTR містить 01 (початкове значення). Поле PAGECTR - визначене як PAGECTR DB '01'. У результаті буде згенеровано число в ASCII коді - тичина. 3031. Процедура M10PAGE збільшує лічильник PAGECTR на 1 так, що значення стає послідовно 3032, 3033 і т.д. Ці значення коректні до 3039, далі випливає 303A, яке буде роздруковано, як двокрапка (:). Тому, якщо в правому байті лічильника PAGECTR з'являється тичина 3A, то це значення заміняється на тичину 30, а до лівого байта додається одиниця. У такий спосіб тичина 303A перекодується в тичину 3130, тобто в 10 у символьному представленні.

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

ПЕЧАТКА ASCII-ФАЙЛІВ І ТАБУЛЯЦІЯ

Табуляція, яка забезпечується, наприклад, відеоадаптерами, полягає в заміні одного символу табуляції (код 09) декількома пробілами при висновку так, щоб наступна позиція була кратна 8. Таким чином, стандартні позиції табуляції є 8, 16, 24 і т.д. Багато принтерів, однак, ігнорують символи табуляції. Тому, така програма, як DOS PRINT, призначена для печатки ASCII файлів (наприклад асемблерних вихідних текстів) перевіряє кожен символ, посилається на принтер. І, якщо виявляється символ табуляції, то програма видає кілька пробілів до позиції кратної 8.

Програма, приведена на рис 19.2, виводить на екран запит на введення імені файлу і, потім, друкує вміст зазначеного файлу. Ця програма на відміну від приведеної на рис.17.3 (виведення файлів на екран) здійснює заміну виведених символів табуляції на відповідне число пробілів. У результаті символ табуляції в позиціях від 0 до 7 приводить до переходу на позицію 8, від 8 до 15 - на 16 і т.д. Команди, що реалізують дану логіку, знаходяться в процедурі G10XFER після мітки G60. Розглянемо три приклади обробки символу табуляції:


Мова програмування Assembler


У програмі організовані наступні процедури:

З10PRMP Запитує введення імені файлу. Натискання тільки клавіші

Return приводить до завершення роботи програми.

E10OPEN Відкриває дисковий файл по зазначеному імені.

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

P10PRNT Роздруковує вивідний рядок і очищає область висновку.

R10READ Зчитує сектор з дискового файлу.

Коди "повернення каретки", "переклад рядка" і "прогін сторінки" дійсні для будь-яких принтерів. Можна модифікувати програму для підрахунку рядків, що роздруковуються, і виконання прогону сторінки (тичина.OC) при досягненні, наприклад, рядка 62.

Деякі користувачі воліють установлювати символи "прогін сторінки" у ASCII файлах за допомогою текстового редактора в конкретних місцях тексту, наприклад, наприкінці асемблерних процедур. Крім того, можна змінити програму для функції 05 базової версії DOS. Ця функція виконує виведення кожного символу безпосередньо на принтер. Таким чином можна виключити визначення і використання області висновку.

ПЕЧАТКА ПІД КЕРУВАННЯМ БАЗОВОЇ DOS

Для друку в базовій версії DOS необхідно встановити в регістрі AH код функції 05, а в регістр DL помістити символ, що роздруковується, і, потім, виконати команду INT 21H у такий спосіб:


MOV AH,05; Запит функції печатки

MOV DL,char; символ, ЩоРоздруковується

INT 21H; Виклик DOS


За допомогою цих команд можна передавати на принтер керуючі символи. Однак, печатка, звичайно, припускає виведення повного чи часткового рядка тексту і покрокову обробку області даних, відформатова- ної по рядках. Нижче показана програма печатки повного рядка. Спочатку в регістр SI завантажується початкова адреса області HEADG, а в регістр CX - довжина цієї області. Цикл, що починається по мітці P20, виділяє черговий символ з області HEADG і посилає його на принтер. Оскільки перший символ області HEADG - "прогін сторінки", а останні два - "переклади рядка", тому заголовок друкується на початку нової сторінки і після нього випливає подвійний інтервал.

HEADG DB 0CH,'Industrial Bicycle Mfrs',0DH,0AH,0AH

LEA SI,HEADG ;Установка адреси і

MOV CX,27 ; довжини заголовка

P20:

MOV AH,05 ;Запит функції печатки

MOV DL,[SI] ;Символ із заголовка

INT 21H ;Виклик DOS

INC SI ;Наступний символ

LOOP P20


Поки принтер не включений, DOS видає повідомлення "Out of paper". Після включення харчування програма починає працювати нормально. Для припинення печатки можна натиснути клавіші Ctrl/Break.

СПЕЦІАЛЬНІ КОМАНДИ ПРИНТЕРА

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


Мова програмування Assembler


Є команди, що розпізнаються по попередньому символу Esc (тичина.IB). Деякі з них у залежності від друкуючого пристрою представлені нижче:


1B 30 Встановити щільність 8 рядків на дюйм

1B 32 Встановити щільність 6 рядків на дюйм

1B 45 Включити жирний формат

1B 46 Виключити жирний формат

Коди команд можна посилати на принтер двома різними способами:

1. Визначити команди в області даних. Наступний приклад установлює вузький формат, 8 рядків на дюйм, потім друкує заголовок із завершальними командами "повернення каретки" і " переклад рядка":


HEADG DB 0FH, 1BH, 30H, 'Title...', 0DH, 0AH


2. Використовувати команди з безпосередніми даними:


MOV AH,05 ;Запит функції печатки

MOV DL,0FH ;Уключити вузький формат

INT 21H


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

Команда BIOS INT 16H виконує спеціальну операцію, яка відповідно до коду в регістрі AH забезпечує наступні три функції введення з клавіатури.

AH=00: Читання символу. Дана функція поміщає в регістр AL черговий ASCII символ, уведений із клавіатури, і встановлює скен код у регістрі AH. (Скен-коди порозуміваються у наступному розділі). Якщо на клавіатурі натиснута одна з спеціальних клавішею, наприклад, Ноmе чи F1, то в регістр AL заноситься 00. Автоматична луна символу на екран по цієї функції не відбувається.

AH=01: Визначення наявності введеного символу. Дана функція скидає прапор нуля (ZF=0), якщо є символ для читання з клавіатури; черговий символ і скен-код будуть поміщені в регістри AL і AH відповідно і даний елемент залишиться в буфері.

AH=02: Визначення поточного стану клавіатури. Дана функція повертає в регістрі AL стан клавіатури з адреси пам'яті тичина 417:

Біт

7 Стан вставки активно (Ins)

6 Стан фіксації верхнього регістра (Caps Lock) переключено

5 Стан фіксації цифрової клавіатури (Num Lock) переключено

4 Стан фіксації прокручування (Scroll Lock) переключено

3 Натиснута комбінація клавішею Alt/Shift

2 Натиснута комбінація клавішею Ctrl/Shift

1 Натиснута ліва клавіша Shift

0 Натиснута права клавіша Shift

ФУНКЦІОНАЛЬНІ КЛАВІШІ

Клавіатура має три основні типи клавіш:

1. Символьні (алфавітно-цифрові) клавіші: букви від a до z, цифри від 0 до 9, символи %, $, # і т.д.

2. Функціональні клавіші: Ноmе, End, Повернення на позицію, стрілки, Return, Del, Ins, PgUp, PgDn і програмно- функціональні клавіші.

3. Керуючі клавіші: Alt, Ctrl і Shift, що працюють разом з іншими клавішами.

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

Кожна клавіша має власний скен-код від 1 (Esc) до 83 (Del) чи від тичина 01 до тичина 53. За допомогою цих скен-кодів програма може визначити натискання будь-якої клавіші. Наприклад, запит на введення одного символу з клавіатури включає завантаження 00 у регістр AH і звертання до BIOS через INT 16H:


MOV AH,00 ;Функція введення з клавіатури

INT 16H ;Викликати BIOS


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

1. ASCII-код символу A (тичина 41) у регістрі AL;

2. Скен-код для клавіші A (тичина 1E) у регістрі AH.

Якщо натиснута функціональна клавіша (наприклад, Ins) клавіатура також передає два елементи:

1. Нуль у регістрі AL;

2. Скен-код для клавіші Ins (тичина.52) у регістрі AH.

Таким чином, після виконання команди INT 16H необхідно колись перевірити вміст регістра AL. Якщо AL містить нуль, то була натиснута функціональна клавіша, якщо не нуль, то отриманий код - символьної клавіші. Нижче приведений приклад такої перевірки:


MOV AH,00 ;Функція введення

INT 16H ;Викликати BIOS

CMP AL,00 ;Функціональна клавіша?

JZ exit ; так - вийти


Скен-Коди

Клавіатура має по дві клавіші для таких символів як *, + і -. Натискання "зірочки", наприклад, встановлює код символу тичина 2A у регістрі AL і один із двох скен-кодів у регістрі AH в залежності від того, яка з клавіш була натиснута: тичина 09 для зірочки над цифрою 8 чи тичина 29 для зірочки на клавіші PrtSc. Нижче приведена логіка перевірки скен-коду для зірочки:

Мова програмування Assembler


Приведемо приклад програми для установки курсору в рядок 0 і cтовбця 0 при натисканні клавіші Ноmе (скен-код 47):


MOV AH,00 ; Виконати введення з клавіатури

INT 16H ;

CMP AL,00 ; Функціональна клавіша?

JNE EXIT1 ; немає -і вийти

CMP AH,47H ; Скен-код для клавіші Home?

JNE EXIT2 ; немає -і вийти

MOV AH,02 ;

MOV BH,00 ; Установити курсор

MOV DX,00 ; по координатах 0,0

INT 10H ; Викликати BIOS


Функціональні клавіші F1 - F10 генерують скен-коди від тичини 3B до тичини 44. Наступний приклад виконує перевірку на функціональну клавішу F10:

CMP AH,44H ; Клавіша F10?

JE EXIT1 ; Так


За адресою EXIT1 програма може виконати будь-яку необхідну дію. Повний список скен-кодів приводиться в посібнику з мови BASIC. Технічний опис IBM PC містить докладний опис усіх скен-кодів, а також опис використання клавіш Alt, Ctrl і Shift.


Лекція 9


Функції переривання 21h

Функції введення/виведення символу та стрічки

Керування кольором


1. Функції переривання 21h


Переривання 21H є перериванням, через яке відбувається звертання до основним функціям DOS. Це переривання забезпечує доступ до системи введення-висновку, керованої DOS. На рис.5.4 представлені всі можливі функції, що використовують це переривання. Вибір функції в програмі здійснюється за допомогою запису в регістр AH потрібного значення перед виконанням переривання 21H.

ФУНКЦІЇ ПЕРЕРИВАННЯ DOS INT 21H

Нижче приведені базові функції для переривання DOS INT 21H. Код функції встановлюється в регістрі AH:

00 Завершення програми (аналогічно INT 20H).

01 Уведення символу з клавіатури з луною на екран.

02 Виведення символу на екран.

03 Уведення символу з асинх. комунікаційного каналу.

04 Виведення символу на асинх. комунікаційний канал.


2. Функції введення/виведення символу та стрічки


ВИВЕДЕННЯ НА ЕКРАН: БАЗОВА ВЕРСІЯ DOS

Виведення на екран у базовій версії DOS вимагає визначення текстового повідомлення в області даних, установки в регістрі AH значення 09 (виклик функції DOS) і вказівки команди DOS INT 21H. В процесі виконання операції кінець повідомлення визначається по oбмежнику ($), як це показано нижче:


NAMPRMP DB 'Ім'я покупця?','$

MOV AH,09 ;Запит висновку на екран

LEA DX,NAMPRMP ;Завантаження адреси сообщ.

INT 21H ;Виклик DOS


Знак обмежувача "$" можна кодувати безпосередньо після cимвольного рядка (як показано в прикладі), усередині рядка:


Ім'я покупця?$', чи в наступному операторі DB '$'.


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

Команда LEA завантажує адресу області NAMPRMP у регістр DX для передачі в DOS адреси виведеної інформації. Адреса NAMPRMP, що завантажується в DX по команді LEA, є oтносительным, тому для обчислення абсолютної адреси даних DOS складає значення регістрів DS і DX (DS:DX).

ПРОГРАМА: ВИВЕДЕННЯ НА ЕКРАН НАБОРУ СИМВОЛІВ КОДУ ASCII

Більшість з 256 кодів ASCII мають символьне позначення, і можуть бути виведені на екран. Коди 00 і FF не мають символів і виводяться на екран у виді пробілів, хоча символ пробілу має в ASCII шіст. код 20.

На рис. 8.1 показана COM-програма, що виводить на екран повний набір символів коду ASCII. Програма викликає три процедури; B10CLR, C10SET і D10DISP. Процедура B10CLR очищає екран, а процедура C10SET встановлює курсор у положення 00,00. Процедура D10DISP виводить вміст CTR, що на початку иніціалізується значенням 00 і потім збільшується на 1 при кожному висновку на екран, поки не досягне шіст. значення FF.

Оскільки символ долара не виводиться на екран і крім того коди від 08 до 0D є спеціальними керуючими cимволами, тому це приводить до переміщення курсору й іншим керуючим впливам. Завдання: уведіть програму, виконайте асемблювання, компоновку і перетворення в COM-файл. Для запуску програми введіть її ім'я, наприклад, У:ASCII.COM. Перший виведений рядок починається з пробільного символу (тичина.00), двох "усміхнених облич" (тичина. 01 і 02) і трьох карткових символів (тичина.03, 04 і 05). Код 07 видає звуковиття сигнал. Код 06 повинний відобразитися картковим символом "піки", але керуючі символи від тичина 08 до 0D зітруть його. Код 0D є "поверненням каретки" і приводить до переходу на новий (наступний) рядок. Код тичина 0E - представляється у виді музичної ноти. Символи після тичини 7F є графічними. Можна змінити програму для обходу керуючих символів. Нижче приведений приклад фрагмента програми, що дозволяє обійти усі символи між тичинами 08 і 0D. Ви можете поекспериментувати, oбходячи тільки, скажімо, тичину 08 (повернення на символ) і 0D (повернення каретки):


CMP CTR,08H ; Менше ніж 08?

JB D30 ; так - прийняти

CMP CTR,0DH ; Менше/дорівнює 0D?

JBE D40 ; так - обійти

D30:

MOV AH,40H ; Виведення символів < 08

INT 21H ; і > 0D

D40:

INC CTR


УВЕДЕННЯ ДАНИХ ІЗ КЛАВІАТУРИ: БАЗОВА ВЕРСІЯ DOS

Процедура введення даних із клавіатури простіше, ніж виведення на екран. Для введення, що використовує базову DOS, область уведення вимагає наявності cписка параметрів, що містить поля, що необхідні при виконанні команди INT. По-перше, повинна бути визначена максимальна довжина тексту, що вводиться. Це необхідно для попередження користувача звуковим сигна брухт, якщо набраний занадто довгий текст; символи, що перевищують максимальну довжину не приймаються. По-друге, у списку параметрів повинне бути визначене поле, куди команда повертає дійсну довжину введеного тексту в байтах. Нижче приведений приклад, у якому визначений список параметрів для області введення. LABEL являє собою директиву з атрибутом BYTE. Перший байт містить максимальну довжину даних, що вводяться. Оскільки це однобайтове поле, то можливо його максимальне значення - тичина FF чи 255. Другий байт необхідний DOS для занесення в нього дійсного числа введених символів. Третім байтом починається поле, що буде містити введені символи.


NAMEPAR LABEL BYTE ;Список параметрів:

MAXLEN DB 20 ; Максимальна довжина

ACTLEN DB ? ; Реальна довжина

NAMEFLD DB 20 DUP (' ') ; Уведені символи


Оскільки в списку параметрів директива LABEL не займає місця, то NAMEPAR і MAXLEN вказують на той самий aдрес пам'яті. У трансляторі MASM для визначення списку параметрів у виді структури може використовуватися також директива STRUC. Однак, у зв'язку з тим, що посилання на імена, визначені всередині, вимагають спеціальної адресації, утримаємося cейчас від розгляду даної теми до глави 24 "Директиви асемблера". Для запиту на введення необхідно помістити в регістр AH номер функції - 10 (тичина. 0AH), завантажити адреса списку параметрів (NAMEPAR у нашому прикладі) у регістр DX і виконати INT 21H:

MOV AH,0AH ;Запит функції введення

LEA DX,NAMEPAR ;Завантажити адреси списку параметрів

INT 21H ;Викликати DOS


Команда INT очікує поки користувач не введе з клавіатури текст, перевіряючи при цьому, щоб число введених cимволів не перевищувало максимального значення, зазначеного в списку параметрів (20 у нашому прикладі). Для вказівки кінця введення користувач натискає клавішу Return. Код цієї клавіші (тичина. 0D) також заноситься в поле введення (NAMEFLD у нашому прикладі). Якщо, наприклад, користувач ввів ім'я BROWN (Return), то cписок параметрів буде містити інформацію:

дес.: :20:5: В: R: O: W: N: #: : : : : ...

шіст.: :14:05:42:52:4F:57:4E:0D:20:20:20:20: ...

В другий байт списку параметрів (ACTLEN у нашому прикладі) команда заносить довжину введеного імені - 05. Код Return знаходиться за адресою NAMEFLD +5. Символ # використаний тут для індикації кінця даних, тому що 0D не має відображуваного символу. Оскільки максимальна довжина в 20 символів включає тичина.0D, то дійсна довжина що вводиться текстом може бути тільки 19 символів.

ПРОГРАМА: ВВЕДЕННЯ І ВИВЕДЕННЯ ІМЕН

EXE-програма, приведена на рис. 8.2, запитує введення імені, потім відображає в середині екрана введене ім'я і включає звуковий сигнал. Програма продовжує запитувати і відображати імена, поки користувач не натисне Return у відповідь на черговий запит. Розглянемо ситуацію, коли користувач ввів ім'я TED SMITH:

1. Розділимо довжину 09 на 2 одержимо 4, і

2. Віднімемо це значення від 40, одержимо 36

Команда SHR у процедурі E10CENT зрушує довжину 09 на oдин біт вправо, виконуючи таким чином розподіл на 2. Значення біт 00001001 переходить у 00000100. Команда NEG змінює знак +4 На -4. Команда ADD додає значення 40, одержуючи у регістрі DL номер початкового стовпця - 36. При установці курсору на рядок 12 і стовпець 36 ім'я буде виведене на екран у наступному виді:

Рядок 12: TED SMITH

Стовпець: 36 40

У процедурі E10CODE існує команда, що встановлює cимвол звукового сигналу (07) в області введення безпосередньо після імені:


MOV NAMEFLD[BX],07


Попередня команда встановлює в регістрі BX значення довжини, і команда MOV потім, комбінуючи довжину в регістрі BX і адресу поля NAMEFLD, пересилає код 07. Наприклад, при довжині імені 05 код 07 буде поміщений за адресою NAMEFLD+05 (заміщаючи значення коду Return). Остання команда в процедурі E10CODE встановлює обмежувач "$" після коду 07. Таким чином, коли процедура F10CENT виводить на екран ім'я, то генеpується також звуковий сигнал.

Уведення єдиного символу Return

При введенні імені, що перевищує по довжині максимальне значення, зазначене в списку параметрів, виникає звуковий сигнал і система oчікує уведення тільки символу Return. Якщо узагалі не вводити ім'я, а тільки натиснути клавішу Return, то система прийме її і yстановить у списку параметрів нульову довжину в такий спосіб: Список параметрів (тичина.): :14:00:0D:. Для позначення кінця імен, що вводяться, користувач може просто натиснути Return у відповідь на черговий запит на введення імені. Прогpамма визначає кінець уведення по нульовій довжині.

Заміна символу Return

Значення, що вводяться, можна використовувати для самих різних цілей, наприклад: для печатки повідомлень, збереження в таблиці, запису на диск. При цьому, можливо, з'явиться необхідність заміни символу Return (тичина.0D) в області NAMEFLD на символ пробілу (тичина.20). Поле NAMELEN містить дійсну або відносну довжину адреси коду 0D. Якщо, наприклад, NAMELEN містить довжину 05, то адреса коду 0D дорівнює NAMEFLD+5. Можна занести цю довжину в регістр BX для індексної адресації в поле NAMEFLD:


MOV BH,00 ;Установити в регістрі BX

MOV BL,NAMELEN ; значення 0005

MOV NAMEFLD[BX],20H ;Замінити 0D на пробіл


Третя команда MOV заносить символ пробілу (тичина.20) по адресі, визначенній першим операндом: адреса поля NAMEFLD плюс вміст регістра BX, тобто NAMEFLD+5.


3. Керування кольором


БАЙТ АТРИБУТІВ

Байт атрибутів, як для монохромного, так і для графічного дисплея в текстовому (не графічному) режимі визначає характеристики кожного відображуваного символу. Атрибут-байт-атрибут має наступні 8 біт:

Фон Текст

Атрибут: BL R G B I R G B

Номер бітів: 7 6 5 4 3 2 1 0

Букви RGB представляють бітові позиції, керуючі червоним (red), зеленим (green) і синім (blue) променем у кольоровому моніторі. Біт 7 (BL) установлює миготіння, а біт 3 (I) - рівень яскравості. На монохроматичних моніторах текст висвічується зеленим чи жовтогарячим на темному фоні, хоча в даному розділі таке зображення називається чорно-білим (BW). Для модифікації атрибутів можна комбінувати біти наступним чином:

Ефект виділення Фон Текст

RGB RGB

Невідображуваний (чорний по чорному) 000 000

Підкреслення (не для кольору) 000 001

Нормальний (білий по чорному) 000 111

Інвертований (чорний по білому) 111 000

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

Двійковий Тичина. Ефект виділення

код код

0000 0000 00 Невідображуваний (для паролів)

0000 0111 07 Білий по чорному (нормальний)

1000 0111 87 Білий по чорному (миготіння)

0000 1111 0F Білий по чорному (яскравий)

0111 0000 70 Чорний по білому (інвертований)

1111 0000 F0 Чорний по білому (инверт. миготливий)

Ці атрибути підходять для текстового режиму, як для монохромних, так і для кольорових дисплеїв. У наступній главі буде показано, як вибирати конкретні кольори. Для генерації атрибуту можна використовувати команду INT 10H. При цьому регістр BL повинен містити значення байта-атрибута, а регістр AH один з наступних кодів: 06 (прокручування нагору), 07 (прокручування вниз), 08 (уведення чи атрибута символу), 09 (виведення атрибута чи символу). Якщо програма встановила деякий атрибут, то він залишається таким, доки програма його не змінить. Якщо встановити значення байта атрибута рівним тичина.00, то символ взагалі не буде відображений.


Лекція 10


Переривання 10h

Функції екранного режиму. Функції малювання крапки та прямої

Керування кольором


1. Переривання 10h


Переривання INT 10H забезпечує керування всім екраном. В регістрі AH встановлюється код, що визначає функцію переривання. Команда зберігає зміст регитрів BX, CX, DX, SI і BP. Нижче описані всі можливі функції.

AH=00: Установка режиму. Дана функція дозволяє периключати кольоровий монітор у текстовий чи графічний режим. Установка pежиму для виконуваної в сучасний момент програми здійснюється c допомогою INT 10H. При установці відбувається очищення екрану. Зміст регістру AL може бути наступним:

00 40 х 25 чорно-білий текстовий режим

01 40 х 25 стандартний 16-кольоровий текстовий режим

02 80 х 25 чорно-білий текстовий режим

03 80 х 25 стандартний 16-кольоровий текстовий режим

04 320 х 200 стандартний 4-кольоровий графічний режим

05 320 х 200 чорно-білий графічний режим

06 640 х 200 чорно-білий графічний режим

07 80 х 25 чорно-білий стандартний монохроматичний

08 - 0A формати для моделі PCjr

0D 320 х 200 16-кольоровий графічний режим (EGA)

0E 640 х 200 16- кольоровий графічний режим (EGA)

0F 640 х 350 чорно-білий графічний режим (EGA)

10 640 х 350 64- кольоровий графічний режим (EGA)

EGA (Enhanced Graphics Adapter) - позначає удосконалений графічний адаптер. Наступний приклад показує установку стандартного 16- кольорового текстового режиму


MOV AH,00 ;Функція установки режиму

MOV AL,03 ;Стандартний кольоровий текст 80 х 25

INT 10H ;Викликати BIOS


Для визначення типу адаптера, встановленого в системі, служить переривання BIOS INT 11H. Дана команда повертає в регістрі AX значення, в якому біти 5 і 4 вказують на відео режим:

01 40 х 25 чорно-білий режим у кольоровому адаптері

10 80 х 25 чорно-білий режим у кольоровому адаптері

11 80 х 25 чорно-білий режим у чорно-білому адаптері

Програма, що працює з невідомим типом монітора, може перевірити тип по регістру AX після INT 11H і потім встановити необхідний режим. AH=01: Установка розміру курсору. Курсор не є символом з набору ASCII-кодів. Комп'ютер має власне апаратне забезпечення для керування видом курсору. Для цього існує спеціальна обробка по INT перериванню. Звичайно символ курсоpа схожий на символ підкреслення. Використовуючи INT 10H, можна керувати вертикальним розміром курсору: біти 4-0 у регістрі CH для верхньої лінії сканування, а біти 4-0 у регістрі CL - для нижньої. Можна встановити будь-який pозмір курсору по вертикалі: від 0 до 13 для монохроматичних і EGA монітоpів і від 0 до 7 для більшості кольорових моніторів. Наведемо приклад для збільшення розміру курсору від його верхньої до нижньої лінії сканування:


MOV AH,01 ;Встановити розмір курсору

MOV CH,00 ;Верхня лінія сканування

MOV CL,13 ;Нижня лінія сканування

INT 10H ;Викликати BIOS


В результаті виконання цих команд курсор перетвориться в суцільний мигітливий прямокутник. Можна встановити будь-який розмір курсору між верхньою і нижньою границями, наприклад, 04/08, 03/10 і т.д. Курсор зберігає свій вигляд, поки програма не змінить його. Використання розмірів 12/13 (для моно) і 6/7 (для кольору) переводить курсор у його нормальний вигляд.

AH=02: Установка позиції курсору. Ця функція встановлює курcор у будь-яку позицію на екрані відповідно до координатами cтрічки і стовпця. Номер сторінки звичайно дорівнює 0, але може мати значення від 0 до 3 при 80 стовпцях на екрані. Для установки позиції курсору необхідно занести в регістр AH значення 02, у регістр BH номер сторінки і в регістр DX координати рядка і стовпця:


MOV AH,02 ;Встановити положення курсору

MOV BH,00 ;Сторінка 0

MOV DH,рядок ;Рядок

MOV DL,стовпець ;Стовпець

INT 10H ;Викликати BIOS


AH=03: Читання поточного положення курсору. Програма може визначити положення курсору на екрані (рядок і стовпець), а також pозмір курсору, у такий спосіб:


MOV AH,03 ;Визначити положення курсору

MOV BH,00 ;Встановити сторінку 0

INT 10H ;Викликати BIOS


Після повернення регістр DH буде містити номер рядка, а регістр DL-номер стовпця. У регістрі CH буде верхня лінія cканування, а в регістрі CL -нижня.

AH=04: Читання положення світлового пера. Дана функція використовується в графічному режимі для визначення положення світлового пеpа.

AH=05: Вибір активної сторінки. Нова сторінка встановлюється для кольорових текстових режимів від 0 до 3. Для режиму 40 х 25 можливо встановлювати до 8 сторінок (від 0 до 7), а для режиму 80 х 25 - до 4 сторінок (від 0 до 3).


MOV AH,05 ;Встановити активну сторінку

MOV AL,сторінка ;Номер сторінки

INT 10H ;Викликати BIOS


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

Раніше код 06 використовувався для очищення екрану. В текстовому режимі установка в регістрі AL значення 00 призводить до повного прокручування нагору всього екрану, очищаючи його пробілами. Установка ненульового значення в регістрі AL визначає кількість рядків прокручування екрану нагору. Верхні рядки ідуть з екрану, а чисті рядки вводяться знизу. Наступні команди виконують прокручування всього екрану на один рядок:


MOV AX,0601H ;Прокрутити на один рядок нагору

MOV BH,07 ;Атрибут: нормальний, чорно-білий

MOV CX,0000 ;Координати від 00,00

MOV DX,184FH ;до 24,79 (повний екран)

INT 10H ;Викликати BIOS


Для прокручування будь-якої кількості рядків необхідно встановити відповідне значення в регістрі AL. Регістр BH містить атрибут для нормального чи інвертованого відображення, миготіння, установки кольору і т.д. Значення в регістрах CX і DX дозволяють прокручувати будь-яку частину екрану. Нижче наведений стандартний підхід до прокручування:

1. Визначити в елементі ROW (рядок) значення 0 для установки рядка положення курсору.

2. Видати текст і просунути курсор на наступний рядок.

3. Перевірити, чи знаходиться курсор на останньому рядку (CMP ROW,22).

4. Якщо так, то збільшити елемент ROW (INC ROW) і вийти.

5. Якщо ні, то прокрутити екран на один рядок і, використовуючи ROW перемістити курсор.

AH=07: Прокручування екрану вниз. Для текстового режиму прокручування екрану вниз позначає видалення нижніх рядків і вставка чистих рядків зверху. Регістр AH повинен містити 07, значення інших регістpів аналогічні функції 06 для прокручування нагору.

AH=08: Читання атрибуту/символу в поточній позиції курсору. Для читання символу і байта атрибута з дисплейного буфера, як у текстовому, так і в графічному режимі використовуються наступні команди:


MOV AH,08 ;Запит на читання атр./симв.

MOV BH,00 ;Сторінка 0 (для текстового реж.)

INT 10H ;Викликати BIOS


Дана функція повертає в регістрі AL значення символу, а у AH - його атрибут. У графічному режимі функція повертає тичина. 00 для не ASCII-кодів. Оскільки ця функція читає тільки один cимвол, то для символьного рядка необхідна організація циклу.

AH=09: Виведення атрибута/символу в поточну позицію курсору. Для висновку на екран символів у текстовому чи графічному режимі з установкою миготіння, інвертування і т.д. можна скористатися наступними командами:


MOV AH,09 ;Функція висновку

MOV AL,символ ;Виведений символ

MOV BH,сторінка ;Номер сторінки (текст.реж.)

MOV BL,атрибут ; чиАтрибут колір

MOV CX,повторення ;Число повторень символу

INT 10H ;Викликати BIOS


У регістр AL повинний бути поміщений виведений на екран символ. Значення в регістрі CX визначає число повторень символу на екрані. Виведення на екран послідовності різних символів вимагає організації циклу. Дана функція не переміщує курсор. У наступному прикладі на екран виводиться п'ять мигітливих "серденьок" в інвертованому вигляді:


MOV AH,09 ;Функція висновку

MOV AL,03H ;Хробаки (карткова масть)

MOV BH,00 ;Сторінка 0 (текст. режим)

MOV BL,0F0H ;Миготіння, інверсія

MOV CX,05 ;П'ять разів

INT 10H ;Викликати BIOS


В текстовому (але не в графічному) режимі символи автоматично виводяться на екран і переходять з одного рядка на інший. Для висновку на екран тексту чи запиту повідомлення необхідно скласти програму, що встановлює в регістрі CX значення 01 і в циклі завантажує в регістр AL з пам'яті виведені символи тексту. Оскільки регістр CX у даному випадку зайнятий, то не можна використовувати команду LOOP. Крім того, при висновку кожного символу необхідно додатково просувати курсор у наступний стовбець (функція 02).

В графічному режимі регістр BL використовується для визначення кольору графіки. Якщо біт 7 дорівнює 0, то заданий колір замінює поточний колір крапки, якщо біт 7 дорівнює 1, то відбувається комбінація кольорів за допомогою команди XOR.

AH=0A: Виведення символу в поточну позицію курсору. Єдина різниця між функціями 0A і 09 полягає в тому, що функція 0A не встановлює атрибут:


MOV AH,0AH ;Функція виведення

MOV AL,символ ;Виведений символ

MOV BH,сторінка ;Номер сторінки (для тексту)

MOV CX,повторення ;Число повторень символу

INT 10H ;Викликати BIOS


Для більшості застосувань команда переривання DOS INT 21H більш зручна.

AH=0E: Виведення у режимі телетайпа. Дана функція дозволяє використовувати монітор, як простий термінал. Для виконання цієї функції необхідно встановити в регістрі AH тичину значення 0E, у pегістр AL помістити виведений символ, колір тексту (у графічному режимі) занести в регістр BL і номер сторінки для текстового режиму - у регістр BH. Звуковий сигнал (код 07H), повернення на одну позицію (08H), кінець рядка (0AH) і повернення каретки (0DH) діють, як команди для форматування екрану. Дана функція автоматично просуває курсор, переводить символи на наступну cтрічку, виконують прокручування екрану і зберігає поточні атрибути екрану.

AH=0F: Одержання поточного відео режиму. Дана функція повертає в регістрі AL поточний відео режим (див.функцію AH=00), в pегістрі AH - число символів в рядку (20, 40 чи 80), у регістрі BH - номер сторінки.

AH=13: Встановлення символьного рядка (тільки для AT). Дана функція дозволяє на комп'ютерах типу AT виводити на екран символьні рядки з установкою атрибутів і переміщенням курсору:


MOV AH,13H ;Функція висновку на екран

MOV AL,сервіс ;0, 1, 2 чи 3

MOV BH,сторінка ;

LEA BP,адреса ;Адреса рядка в ES:BP

MOV CX,довжина ;Довжина рядка

MOV DX,екран ;Координати на екрані

INT 10H ;Викликати BIOS


Можливий наступний додатковий сервіс:

0 - використовувати атрибут і не переміщати курсор;

1 - використовувати атрибут і перемістити курсор;

2 - вивести символ, потім атрибут і не переміщати курсор;

3 - вивести символ, потім атрибут і перемістити курсор.


2. Функції екранного режиму. Функції малювання крапки та прямої


ГРАФІЧНИЙ РЕЖИМ

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

1. Низький дозвіл (не підтримується в ROM) забезпечує встановлення 100 рядків по 160 крапок (тобто чотири біти на крапку). Кожна крапка може мати один з 16 стандартних квітів, як описано в попередньому розділі "Кольору". Реалізація даного режиму включає пряму адресацію контролера Motorola 6845 CRT. Для цього використовуються два порти: тичина.3D4 і 3D5.

2. Середній дозвіл для стандартної кольорової графіки забезпечує 200 рядків по 320 крапок. Кожен байт у цьому випадку представляє чотири крапки (тобто два біти на крапку).

3. Високий дозвіл забезпечує 200 рядків по 640 крапок. Оскільки в даному випадку потрібно 16ДО байт пам'яті, високий дозвіл досягається тільки в чорно-білому (BW) режимі. Кожен байт тут представляє 8 крапок (т.е. один біт на крапку). Нульове значення біта дає чорний колір крапки, одиничне - білий.

Помітимо, що в графічному режимі ROM містить крапкові вигляди тільки для перших 128 ASCII-кодів. Команда INT 1FH забезпечує доступ до 1ДО байтової області в пам'яті, визначальної інші 128 символів. (8 байт на символ). Відображення графічних байтів у відео сигнали аналогічно, як для середнього, так і для високого pазрешения.

РЕЖИМ СЕРЕДНЬОГО ДОЗВОЛУ

При середньому дозволі кожен байт представляє чотири крапки, пронумерованих від 0 до 3:

Байт: :C1 C0:C1 C0:C1 C0:C1 C0:

Піксели: 0 1 2 3

У будь-який момент для кожної крапки можливі чотири кольори, від 0 до 3. Обмеження в 4 кольори підрозумівається тим, що двобітова крапка має 4 комбінації значень бітів: 00, 01, 10 і 11. Можна вибpати значення 00 для кожного з 16 можливих квітів чи фону вибрати значення 01, 10, і 11 для однієї з двох палітр. Кожна палітpа має три кольори:

C1 C0 Палітра 0 Палітра 1

0 0 фон фон

0 1 зелений голубий

1 0 червоний бузковий

1 1 коричневий білий

Для вибору кольору палітри і фону використовується INT 10H. Таким чином, якщо, наприклад, обраний фон жовтого кольору і палітра 0, то можливі наступні кольори крапки: жовтий, зелений, червоний і коричневий. Байт, що містить значення 10101010, відповідає червоним крапкам. Якщо вибрати колір фону - синій і палітру 1, то можливі кольори: синій, блакитний, бузковий і білий. Байт, що містить значення 00011011, відображає синю, блакитну, бузкову і білу крапки. Переривання BIOS INT 10H для графіка Функція AH=00 команди INT 10H встановлює графічний режим. Функція AH=11 команди INT 10H дозволяє вибрати колір палітри і вивести на екран графічний символ. Код у регіст- рі AH визначає функцію: AH=00: Установка режиму. Нульове значення в регістрі AH і 04 у pегістрі AL установлюють стандартний кольоровий графічний режим:


MOV AH,00 ;Функція установки режиму

MOV AL,04 ;Дозвіл 320х200

INT 10H


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

AH=0BH: Установка колірної палітри. Число в регістрі BH визначає призначення регістра BL: BH=00 вибирає колір фону і бордюру відповідно до змісту pегістра BL. Колір фону від 1 до 16 відповідає тичина значенням oт 0 до F;

BH=01 вибирає палітру відповідно вмісту регістра BL (0 чи 1):


MOV AH,0BH ;Функція установки кольору

MOV BH,01 ;Вибір палітри

MOV BL,00 ; 0 (зелений, червоний, корич.)

INT 10H ;Викликати BIOS


Палітра, встановлена один раз, зберігається, поки не буде скасована іншою командою. При зміні палітри весь екран змінює колірну комбінацію. При використанні функції AH=0BH у текстовому режимі, значення, установлене для кольору 0 у палітрі, визначає колір бордюру.

AH=0CH: Виведення крапки на екран. Використання коду 0C у регістрі AH дозволяє вивести на екран крапку в обраному кольорі (фон і палітра). Наприклад, для дозволу 320х200 завантажимо в регістр DX вертикальну координату (від 0 до 199), а в регістр CX - горизонтальну координату (від 0 до 319). У регістр AL помістимо колір крапки (від 0 до 3):


MOV AH,0CH ;Функція висновку крапки

MOV AL,колір ;Колір крапки

MOV CX,стовпець ;Горизонтальна координата

MOV DX,рядок ;Вертикалькая координата

INT 10H ;Викликати BIOS


AH=0DH: Читання крапки з екрана. Дана функція дозволяє прочитати крапку для визначення її кольору. У регістр DX повинна бути завантажена вертикальна координата (від 0 до 199), а в регістр CX - горизонтальна (від 0 до 319). У регістрі AH повинне бути значення 0D. Функція повертає колір крапки в регістрі AL.


Лекція 11


Поняття "середовища години виконання програми" та "системні змінні"

PSP та отримання доступу до командної стрічки

Доступ до системних змінних з програми


1. Поняття "середовища години виконання програми" та "системні змінні"


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

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


2. PSP та отримання доступу до командної стрічки


Префікс програмного сегмента (PSP) займає 256 (тичина 100) байт і завжди передує в пам'яті кожної COM- чи EXE-програмі, що повинна бути виконана. PSP містить наступні поля:

00 Команда INT 20H (тичина.CD20).

02 Загальний розмір доступної пам'яті у форматі хххх0. Наприклад, 512K вказується як 8000 замість 80000.

04 Зарезервовано.

05 Довгий виклик диспетчера функцій DOS.

OA Адреса підпрограми завершення.

OE Адреса підпрограми реакції на Ctrl/Break.

12 Адреса підпрограми реакції на фатальну помилку.

16 Зарезервовано.

2C Сегментна адреса середовища для збереження ASCIIZ рядків.

50 Виклик функцій DOS (INT 21H і RETF).

5C Параметрична область 1, форматована як стандартний невідкритий блок керування файлів (FCB№1).

6C Параметрична область 2, форматована як стандартний невідкритий блок керування файлім (FCB№2); перекривається, якщо блок FCB№1 відкритий.

80-FF Буфер передачі даних (DTA).

Буфер передачі даних DTA

Дана частина PSP починається за адресою тичина.80 і являє собою буферну область уведення-висновку для поточного дисковода. Вона містить у першому байті число, що вказує скільки разів були натиснуті клавіші на клавіатурі безпосередньо після введення імені програми. Починаючи з другого байта, знаходяться введені символи (якщо такі існують). Далі випливає всіляке "сміття", що залишилося в пам'яті після роботи попередньої програми. Наступні приклади демонструють призначення буфера DTA:

Приклад 1. Команда без операндів. Припустимо, що ви визвали програму CALCIT.EXE для виконання за допомогою команди CALCIT [return]. Після того, як DOS побудує PSP для цієї програми, він установить у буфері за адресою тичина.80 значення тичина.000D. Перший байт містить число символів, уведених із клавіатури після імені CALCIT, крім символу "повернення каретки". Оскільки крім клавіші Return не було натиснуто ні однієї, то число символів дорівнює нулю. Другий байт містить символ повернення каретки, тичина.0D. Таким чином, по адресах тичина.80 і 81 на ходятся 000D.

Приклад 2. Команда з текстовим операндом. Припустимо, що після команди був зазначений текст (але не ім'я файлу), наприклад, COLOR BY, що позначає виклик програми COLOR і передачу цій програмі параметра "BY" для установки блакитного кольору на жовтому фоні. У цьому випадку, починаючи з адреси тичина.80, DOS установить наступні значення байтів:

80:03 20 42 59 0D

Ці байти позначають довжину 3, пробіл, "BY" і повернення каретки.

Приклад 3. Команда з ім'ям файлу в операнде. Програми типу DEL (видалення файлу) припускають після імені програми введення імені файлу як параметр. Якщо буде введено, наприклад, DEL B:CALCIT.OBJ [return], то PSP, починаючи з адрес тичина.5C і тичина.80, буде містити:

5C: 02 43 41 4C 43 49 54 20 20 4F 42 4A

C A L C I T O B J

80: 0D 20 42 3A 43 41 4C 43 49 54 2E 4F 42 4A 0D B : C A L C I T . 0 B J

Починаючи з адреси 5C, знаходиться невідкритий блок FCB, що містить ім'я файлу, що був зазначений у параметрі, CALCIT.OBJ, але не ім'я виконуваної програми. Перший символ вказує номер дисковода (02=B у даному випадку). Слідом за CALCIT знаходяться два пробіли, що доповнюють ім'я файлу до восьми символів, і тип файлу, OBJ. Якщо ввести два параметри, наприклад:


progname A:FILEA,B:FILEB


тоді DOS побудує FCB для FILEA по зсуві тичина 5C і FCB для FILEB по зсуві тичина.6C. Починаючи з адреси 80 у цьому випадку міститься число введених символів (довжина параметрів) - 16, пробіл (тичина.20) A:FILEA,B:FILEB і символ повернення каретки (OD).

Оскільки PSP безпосередньо передує вашій програмі, то можливий доступ до області PSP для обробки зазначених чи файлів або для виконання визначених дій. Для локалізації буфера DTA COM-програма може просто помістити тичину.80 у регістр SI і одержати доступ у такий спосіб:


MOV SI,80H;Адреса DTA

CMP BYTE PTR [SI],0;У буфері нуль?

JE EXIT


Для EXE-програми не можна з упевненістю затверджувати, що кодовий сегмент безпосередньо розташовується після PSP. Однак, тут при ініціалізації регістри DS і ES містять адреса PSP, так що можна зберегти вміст регістра ES після завантаження регістра DS:


MOV AX,DSEG

MOV DS,AX

MOV SAVEPSP,ES


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


MOV SI,SAVEPSP

CMP BYTE PTR [SI+ 80H],0;У буфері нуль?

JE EXIT


DOS версії 3.0 і страше містить команду INT 62H, завантажую щую в регістр BX адреса поточного PSP, якому можна использо вать для доступу до даних у PSP.


3. Доступ до системних змінних з програми


Спеціалізованої функції для доступу до змінних середовища не існує. Однак, аналізуючи слово в PSP під адресою 2c (вказівник на сегмент з копією стану середовища), можна вийти на масив системних змінних, і таким чином дістати потрібну змінну.

Кожна з системних змінних зберігається у вигляді стрічки, що закінчується нулем, саме так, як їх було визначено в config.sys чи autoexec.bat. Використовуючи мнемоніку асемблера, можемо написати так:


db ‘PATH=C:\Windows’,0

db ‘PROMPT=$p$g’,0


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


Лекція 12


Системні змінні BIOS та робота з ними за допомогою прямих посилань

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

Поля дані відеопрограми

Секція поля даних BIOS, має заголовок VIDEO DISPLAY DATA AREA і починається із зсуву 49H, містить змінну, яка використовується відеопрограмою. Усі ці осередки даних містять значення, які використовуються для роботи з дисплейним адаптером у даний момент часу. Багато хто з цих значень копіюють дані, що знаходяться в регістрах дисплейних адаптерів, з яких заборонене читання. Відеопрограма BIOS повинна знати поточне значення таких змінних, як CRT_MODE_SET і CRT_PALETTE при модифікаці регістра. На відміну від порту висновку на системній платі (порт 61H), BIOS не може прочитати ці регістри перед їхньою зміною. Це означає, що BIOS повинен підтримувати в пам'яті образ регістра.

Усі поля даних мають змістовні коментарі, що пояснюють призначення даних під час вашої роботи з текстом BIOS. Окремого коментаря заслуговує поле CURSOR_POSN. Оскільки кольоровий графічний адаптер може підтримувати більше однієї сторінки зображення в текстовому режимі, тому на кожній сторінці існує своє місце для курсору. Контролер CRT 6845 обслуговує тільки курсор поточної сторінки. Коли BIOS переключається зі сторінки на сторінку, контролер запам'ятовує положення курсора на відповідній сторінці. Оскільки кольорова плата може містити максимум вісім сторінок у 40-символьному режимі, тому існує вісім осередків для збереження поточного положення курсору на кожній сторінці.

Функції відеопрограми

Програма дисплея BIOS має багато функцій. У зв'язку з тим, що відеопрограма має так багато функцій, вона використовує таблицю переходів до цих функцій. Ця таблиця названа M1 і містить зсув кожної крапки входу програми дисплея BIOS. Перша частина програми VIDEO_IO витягає код з регістра AH і перетворить його на адресу переходу. Перша частина програми виконує ще і деякі інші дії, включаючи перевірку поля EQUIP_FLAG.

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

Кожного разу, коли програма викликає відеопрограму BIOS, вона визначає, який дисплейний адаптер існує в системі за допомогою перевірки бітів поля EQUIP_FLAG, що відповідають поточному дисплею. Якщо біти 5 і 4 обоє рівні 1, то в системі присутній монохромний адаптер. Будь-яка інша установка біт говорить про те, що в системі працює кольоровий адаптер. Фірма IBM написала цю програму таким чином, виходячи з того, що система може мати тільки один дисплейний адаптер. Перед першим включенням машини ви повинні установити перемикачі на системній платі в положення, що показує, який адаптер дисплея використовується.

Інформація прапорів устаткування в полі EQUIP_FLAG визначає, яку з адрес буфера буде використовувати відеопрограма BIOS. Для монохромної плати BIOS завантажує в регістр ES значення 0B000H, а для кольорової плати - значення 0B800H. Це дозволяє іншим програмам дисплея BIOS працювати без використання інформації про те, який адаптер працює в системі. Усі посилання до буфера робляться щодо регістра ES.

Ви можете вирішити, що, оскільки поле EQUIP_FLAG показує, який адаптер використовується, можна переключатися від одного адаптера до іншого просто змінюючи біти в слові прапорів. На жаль, це не так, адреса введення-висновку контролера 6845 відрізняється для двох адаптерів, і BIOS записує цю базову адресу у свою область даних. Відеопрограма BIOS заносить у змінну ADDR_6845 ця адреса тільки при ініціалізації адаптера (команда AH = 0). Тому переключення від одного дисплея до іншого також вимагає коректування цієї змінної.

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

Фірма IBM опублікувала методи зміни одного дисплея іншим, як за допомогою програми мовою асемблера, так і за допомогою програми на Бейсике. У цих методах потрібно для вказівки адаптера, що ви хочете використовувати, змінити змінну EQUIP_FLAG, а потім використовувати відеопереривання INT 10H при AH = 0. Ця функція инициализирует адаптер і забезпечує правильну установку всіх полів дані програми BIOS. Після цього BIOS може працювати з тим дисплейним адаптером, що зазначений. При цьому картинка на іншому дисплеї залишається видимої. Крім того, дисплейний буфер того адаптера продовжує відображати будь-які зміні тексту і графіки, занесеної в нього. Так що ви можете змінювати вміст дисплейного буфера за допомогою вашої програми (а не за допомогою BIOS), щоб скорегувати інформацію, яка знаходиться на екрані, з якого ви тільки що переключилися.

Давайте розглянемо простий приклад. Ви маєте IBM PC із двома адаптерами - кольоровим графічним і монохромний, і до кожного адаптера підключений дисплей. Коли ви спочатку включаєте машину, система використовує монохромний дисплей. Саме з обліком цього ви і повинні установити перемикачі на системній платі, тому що монохромний дисплей може бути пошкоджений, якщо не буде ініціалізований відразу ж після включення живлення. Інструкція по роботі рекомендує, щоб ви установили перемикачі в положення, яка показує, що в системі присутній монохромний адаптер. Після цього ви можете використовувати відеопрограму BIOS з монохромним дисплеєм. Щоб перейти на кольоровий адаптер, можна виконати програму на рис.П9.7. Ця програма включає кольоровий адаптер у 80-символьному текстовому режимі. Символи, що були висвітлені на монохромному дисплеї, на ньому і залишаються, а ви тепер можете використовувати відеопрограму BIOS для роботи з кольоровим графічним дисплеєм. Але якщо вам буде потрібно змінити вміст монохромного дисплея, ви зможете зробити це, записавши нові символи чи атрибути в буфер дисплея за адресою 0B000H. Це не змінить положення курсору, але змінить картинку. У цьому випадку якщо ви хочете змінювати текст одночасно на кольоровому і монохромному дисплеях, ви повинні написати власну програму обслуговування монохромного дисплея. Чи ви можете з'ясувати, які значення треба змінити в полі даних BIOS, щоб курсор перейшов назад, і виконав потрібні дії, не ініціалізувавши адаптер щоразу.

Установка режиму

Коли програма виконує переривання INT 10H при AH = 0, вона викликає функцію установки режиму відеопрограми BIOS. Якщо в змінної EQUIP_FLAG відзначено, що в системі є монохромна плата, не важливо, яке значення виявилося в регістрі AL. У цьому випадку програма BIOS набудовує монохромний адаптер на режим 7, що означає текстовий режим 80*50, підтримуваний чорно-білою платою.

У випадку кольорової графічної плати значення в регістрі AL визначає, у який із двох графічних чи двох текстових режимів уведе програма BIOS дисплейний адаптер. Ви бачите, що існують чорно-білі режими поряд з кольоровими для тексту, а також графіка 320*200. Ці чорно-білі режими насправді не виключають кольору, вони тільки виключають сигнал кольоровості, що використовується в телевізорі для визначення кольору кожної крапки. Якщо ви використовуєте RGB-монітор, кольори залишаться на місцях. Якщо ж ви використовуєте кольоровий (чи чорно-білий) чи відеомонітор телевізор, установка чорно-білого режиму кольорової плати виключить кольори і дасть більш чітке зображення на екрані. Якщо ви займаєтеся задачею, у якій кольори не потрібні, то одержати трохи краще зображення можна, вибравши один з чорно-білих режимів замість кольорового.

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

Функції відеопрограми, що відповідають номерам від 1 до 5 служать для роботи з регістрами мікросхеми 6845. Як ви пам’ятаєте з опису системної апаратури, мікросхема 6845 містить регістри, що керують формою і положенням курсору, а також тимчасовими характеристиками відображення. Ці підпрограми відеопрограми BIOS дозволяють модифікувати відображення, не знаючи базової адреси мікросхеми 6845. Ці підпрограми входять у число сервісних програм BIOS.

Зрушення зображення

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

Ми вже бачили користь зрушення вікон при вивченні операційної системи і мови Бейсік, яке використовували для зрушення BIOS. Якщо працює 80-символьний дисплей, DOS установлює верхній лівий кут вікна зрушення рівним (0, 0), а нижній правий кут (24, 79). Так зрушується весь екран. Але Бейсік використовує двадцять п'ять рядків для індикації стану дисплея, і тільки 24 рядка відводить під зображення програми. Коли Бейсік зрушує екран за допомогою базової системи введення-висновку, він установлює верхній лівий кут у крапці (0, 0), а правий нижній кут - у крапці (23, 79). Із-за того, що останній рядок залишається за межами зрушення, вона не переміщається під час зрушення. У наступній главі приведений приклад зрушення вікна, який викликаний з програми на Бейсіку.

Відеопрограма BIOS виконує зрушення за допомогою переносу символів і атрибутів у дисплейному буфері. Програма зрушення не змінює стартової адреси дисплейного буфера; такий метод зрушення був би швидший, але не дозволяє прикладній програмі визначати, куди повинні потрапити окремі символи. Спосіб зрушення, реалізований у BIOS, підходить для звичайної роботи екрана. Помітимо також, що програма зрушує зображення при необхідності більш ніж на один рядок. Звичайно програма зрушує зображення на один рядок. Функція зрушення відеопрограми BIOS дозволяє зрушити вміст екрана на кілька рядків. Якщо ж кількість рядків зрушення дорівнює нулю, програма BIOS очищає екран. Це - швидкий спосіб очищення всього екрана або його частини.

Коли програма працює в 80-символьному режимі на кольоровому графічному адаптері, вона не може записувати або читати його текст у довільний момент часу. Якщо програма буде модифікувати буфер не в строго визначені моменти часу, на екрані з'являться перешкоди. Оскільки програма зрушення читає і записує великі кількості даних, вона повинна бути написана з урахуванням проблеми перешкод. Якщо подивитися текст програми обслуговування операції зрушення, то можна побачити, що BIOS обслуговує режим 80*25 кольорової плати (змінна CRT_MODE дорівнює 2 чи 3), як спеціальний випадок. У випадку операцій зрушення ця підпрограма BIOS чекає доти, поки не виникне вертикальний зворотний хід променя дисплея. Це означає, що апаратура адаптера видала на екран весь вміст буфера і готова почати новий кадр. (Апаратура адаптера повторює цей процес регенерації екрана 60 разів у секунду). З появою вертикального зворотнього ходу програма BIOS виключає дисплей і виконує зрушення. Коли програма зрушення перемістить усі символи, вона знову включає дисплей. Це викликає коротке миготіння дисплея. Якщо ви уважно подивитеся на екран під час зрушення, то побачте, що верхні його шість рядків трохи темніші інших. Це відбувається із-за того, що операція зрушення займає трохи більше часу, ніж один період регенерації екрана. Тому верхні шість рядків виключаються на два інтервали регенерації, а весь інший екран - тільки на один інтервал. Метод, що допускає появу перешкод на екрані, настільки непривабливий, що описаний метод переважніший. Ви можете написати кілька програм, щоб спробувати інші методи.

Рефетека ру refoteka@gmail.com