Мова програмування Асемблер-86

Вхідний контроль:

1 Що входить до поняття “архітектура мікропроцесорів”?

2 В чому полягає різниця між мовами програмування високого і низького рівнів?

3 Як можуть будуть подані дробові числа в обчислювальній системі?

4 В яких кодах подаються числа зі знаком в обчислювальній системі?

5 Наведіть регістрову модель 16-розрядного МП фірми Intel.

6 Які сегменти існують в основній пам’яті МПС, побудованої на МП фірми Intel?

7 Які способи адресування операндів МП фірми Intel Ви знаєте?

8 Що називається стеком і як його організовано?

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

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

Мова Асемблер мікропроцесорів фірми Intel є досить розвиненою і гнучкою. До складу мови Асемблер-86 входять понад 100 базових команд, відповідно до яких генерується понад 3800 машинних команд; близько 20 директив, призначених для розподілення пам’яті, ініціалізації змінних, умовного асемблювання тощо. Також у ній передбачено використання засобів структурування даних, що є характерним для мов програмування високого рівня.

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

Сукупність команд і директив, що представляють текст програми, називаються початковим модулем. Початкові модулі створюються за допомогою текстового редактора і можуть зберігатися на будь-якому носії у вигляді початкового файла. Цей файл може мати будь-яку назву і розширення .asm. Асемблер перетворює початковий модуль в об’єктний модуль. Ця операція називається трансляцією, а програма, яка її виконує – транслятором. На етапі створення об’єктного модуля виконується перетворення команд Асемблера на машинні команди. У результаті роботи транслятора створюються:об’єктний модуль – файл, який має розширення .obj, файл лістинга, який має розширення .lst і файл перехресних посилань з розширенням .crf. Файл лістинга вміщує код Асемблера початкової програми, для кожної команди якої вказано машинний код і зміщення у кодовому сегменті, крім того, до цього файла входять таблиці з інформацією про мітки і сегменти, які використовуються у програмі і повідомлення про синтаксичні помилки. Імена файлів призначає програміст, вони можуть співпадати, а можуть бути різними.

Після створення об’єктного модуля він оброблюється за допомогоюпрограми-укладача, яка генерує завантажувальний модуль. Це файл, який має розширення .exe і який може виконуватися МПС. Програма-укладач у завантажувальному модулі об’єднує об’єктні модулі, що входять до програми і підключає, за необхідності, бібліотечні модуліі замінює відносні адреси комірок пам’яті на абсолютні, з урахуванням області пам’яті, в яку модуль буде завантажено для виконання. Бібліотечні модулі – це об’єктні файли, які містять найбільш поширені програми. Ім’я завантажувального модуля також призначає програміст. Блок-схему алгоритму підготовки програми на мові Асемблер для її виконання показано на рис. 9.8.

Текст програми на мові Асемблер складається з операторів (речень) чотирьох типів:

- команди, які є символічними аналогами машинних команд МПС;

- макрокоманди – конструкції, які при трансляції програми замінюються на послідовність відповідних команд;

- директиви – інструкції транслятору з виконання певних дій;

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

Мова програмування Асемблер-86 - student2.ru

Рисунок 9.8 – Блок-схема підготовки програми для її виконання

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

- усі літери латинського алфавіту, при цьому великі і малі літери є еквівалентні;

- цифри від 0 до 9;

- спеціальні і розподілювальні символи, до яких відносяться: ?, @, $, _, &, [ ], ( ), < >, { }, +, –, /, *, %, !, “ “, \, =, #,^ і деякі недруковані символи.

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

Ідентифікатор – це послідовність символів, яка визначена програмістом і використовується для іменування об’єктів програми (міток, змінних, назв операцій тощо). Ідентифікатор може складатися з одного або кількох символів, але починатися може лише літерою. Крапка може бути лише першим символом ідентифікатора. Інші спеціальні символи використовувати в ідентифікаторах не дозволяється. Довжина ідентифікатора становить до 255 символів, але транслятор сприймає лише 32 перших символи, інші ігноруються.

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

Рядком символів може бути будь-яка послідовність символів, в якості яких можливо використовувати літери і спеціальні символи, крім символа повернення каретки та перенесення рядка. Рядок символів обов’язково брати у лапки.

Через те, що мікропроцесор може працювати з різними сегментами, то для завантаження і роботи програми необхідно задати сегменти й особливості їх використання. Це робиться за допомогою директиви SEGMENT, яка має вигляд:

{Ім’я сегмента} SEGMENT {Тип вирівнювання} {Тип комбінування} {Клас сегмента} {Тип розміру}
Програма {Ім’я сегмента} END

Розглянемо окремі поля цієї директиви.

Тип вирівнювання – повідомлення програмі-укладачу про адресу початку сегмента. При правильному розміщенні програма виконується швидше. Можливі значення:

- BYTE – вирівнювання не виконується. Початкова адреса сегмента може бути будь-якою;

- WORD – сегмент починається з адреси, яка є кратна 2, при цьому молодший значний біт фізичної адреси дорівнює 0. Виконується вирівнювання по межі слова;

- DWORD – сегмент починається з адреси, яка є кратна 4. Виконується вирівнювання по межі подвійного слова;

- PARA – сегмент починається з адреси, яка є кратна 16, при цьому остання шістнадцяткова цифра фізичної адреси дорівнює 0Н. Виконується вирівнювання по межі параграфа;

- PAGE – сегмент починається з адреси, яка є кратна 256. Виконується вирівнювання по межі сторінки;

- MEMPAGE – сегмент починається з адреси, яка є кратна 4 кбайтам.

За умовчанням тип вирівнювання має значення PARA.

Тип комбінування – повідомлення програмі-укладачу про об’єднання при виконанні сегментів різних модулів програми, які мають однакові імена. Можливі значення:

- PRIVATE – сегмент не об’єднується з іншими сегментами;

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

- COMMON – усі сегменти з однаковими іменами розміщуються за однією адресою. Таким чином, усі сегменти будуть перекриватися і сумісно використовувати пам’ять;

- AT xxxx – розміщує сегмент за абсолютною адресою параграфа, адреса якого задається виразом хххх;

- STACK – визначення сегмента стека. Усі сегменти, що мають однакові імена, об’єднуються таким чином, що їх адреси розраховуються відносно вмісту регістра SS.

Клас сегмента – повідомлення про відповідний порядок включення сегментів при складанні програми із сегментів різних модулів. Програма-укладач з’єднує усі сегменти, що мають однаковий клас. Рекомендується об’єднувати сегменти з однаковим функціональним призначенням (наприклад, сегменти коду програми). Клас сегмента – це рядок, який береться у лапки, наприклад, сегмент коду «CODE».

Тип розміру сегмента – задає розмір сегмента і порядок формування фізичної адреси в ньому, тому що дані можуть бути 16- або 32-розрядними. Може приймати такі значення:

1 USE16 – формування фізичної адреси у такому сегменті виконується тільки з 16-розрядним зміщенням. Розмір такого сегмента 64 кбайт.

2 USE32 – формування фізичної адреси у такому сегменті виконується тільки з 32-розрядним зміщенням. Розмір такого сегмента 4 Гбайт.

Для призначення сегментам конкретного функціонального призначення і закріплення їх за сегментними регістрами використовується директива ASSUME, яка має вид:

ASSUME Назва сегментного регістра; Ім’я сегмента

Для простих програм, що мають по одному сегменту для коду, даних і стека, у найбільш поширених трансляторах TASM i MASM для спрощення директив сегментування уведено директиву зазначення моделі пам’яті MODEL, яка частково керує розміщенням сегментів. Ця директива зв’язує сегменти, які при використанні спрощених директив сегментування мають наперед визначені імена з сегментними регістрами. Обов’язковим параметром цієї директиви є модель пам’яті. У табл. 9.1 наведено назви і значення параметрів директиви MODEL.

У цій таблиці поняття near і far характеризують віддаленість об’єкта від місця використання. Якщо об’єкт розташовано у сегменті разом з кодом і звернутися до нього можливо за допомогою двобайтового зміщення, то це відповідає типу near (близький перехід). При цьому команда модифікує лише вміст вказівника команд ІР. В іншому випадку об’єкт розміщується в іншому сегменті (тип far) і для звернення до нього необхідно надати чотирибайтний вказівник – сегмент: зміщення. При цьому буде модифіковано вміст двох регістрів.

Таблиця 9.1 – Назви і параметри моделей пам’яті

Модель Тип коду Тип даних Призначення моделі
TINY near near Код і дані поєднано в одну групу з ім’ям DGROUP. Використовується для створення програм з розширенням .com
SMALL near near Код займає один сегмент, дані об’єднано у одну групу з ім’ям DGROUP. Ця модель, звичайно, використовується для створення програм мовою асемблера
MEDIUM far near Код займає декілька сегментів, по одному на кожен програмний модуль, що об’єднується. Усі посилання на передачу керування – типу far. Дані поєднано в одній групі. Усі посилання на них – типу near
COMPACT near far Код знаходиться в одному сегменті. Дані можуть бути у різних сегментах. Посилання на них типу far
LARGE far far Код займає декілька сегментів, по одному на кожен програмний модуль, що об’єднується. Усі посилання типу – far

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

- db – резервування пам’яті для даних довжиною 1 байт;

- dw – резервування пам’яті для даних довжиною 2 байта (слово);

- dd – резервування пам’яті для даних довжиною 4 байта (подвійне слово);

- df – резервування пам’яті для даних довжиною 6 байт;

- dq – резервування пам’яті для даних довжиною 8 байт;

- dt – резервування пам’яті для даних довжиною 10 байт.

Нижче наведено приклад використання директив для керування програмою на мові Асемблер.

MODEL SMALL ; Тип моделі пам’яті, що буде

; використовуватися

STACK 256 ; Визначення сегмента стека

DATA SEGMENT ; Визначення сегмента даних

DATA ENDS

CODE SEGMENT ; Визначення сегмента коду

ASSUME CS:CODE,DS:DATA,ES:DATA ; Закріплення сегментних

; регістрів

· ;

· ; Програма

· ;

CODE ENDS ; Кінець коду програми

END ; Закінчення

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

1 Які особливості мови Асемблер забезпечують її використання?

2 Які файли формуються у результаті роботи програми-транслятора?

3 Чому виконання асемблерної програми можливо лише після роботи програми-укладача?

4 Які файли використовує програма-укладач для формування завантажувального модуля?

5 Які оператори (речення) можуть входити до тексту програми на мові асемблера?

6 Які моделі пам’яті Ви знаєте? Чим відрізняються поняття near і far?

7 Які директиви використовуються для опису простих типів даних?

Контрольні питання підвищеної складності:

1 Для чого використовуються різні типи комбінування?

2 Яким чином програмувач задає типи сегментів і особливості їх використання?

3 Які директиви резервування й ініціалізації даних Ви знаєте?

Формат команди

Формат рядка команди складається з кількох полів, деякі з них не є обов’язковими. Формат рядка команди показано на рис. 9.9. У фігурних дужках показано необов’язкові елементи.

Поле мітки Поле команди Поле операндів Поле коментарів
{Мітка:} {Префікс}Команда {операнди} {; Коментар}

Рисунок 9.9 – Формат команди Асемблера

Мітка – це символічне ім’я, що відповідає значенню поточного вмісту лічильника адреси в поточному сегменті коду. Вміст лічильника адреси відповідає значенню регістра-вказівника команд (ІР) при виконанні програми, тому мітка – це адреса команди, до якої необхідно зробити умовний або безумовний перехід. Мітка відокремлюється від інших частин рядка двокрапкою. Максимальна довжина мітки – 31 символ. Кожна мітка у програмі повинна бути унікальною. Як мітки не допускається використовувати службові слова.

Префікс – це елемент команди, який уточнює або модифікує її дію у випадках:

- зміна сегмента, якщо нас не задовольняє значення сегмента за умовчанням;

- зміна розрядності адреси;

- зміна розрядності операнда;

- вказівка на повторення цієї команди.

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

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

- регістр – регістр;

- регістр – пам’ять;

- пам’ять – регістр;

- безпосередній операнд (число) – регістр;

- безпосередній операнд (число) – пам’ять.

Як операнди, що можуть оброблюватися транслятором, використовуються:

- постійні або безпосередні операнди – числа, рядки, імена або вирази, які мають фіксоване значення. Імена, які використовуються як безпосередні операнди, задаються операторами =: або equ;

- адресні операнди – адреси розміщення операндів у пам’яті. Задаються за допомогою двох складових адреси – сегмента і зміщення;

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

- лічильник адреси – це специфічний вид операнда, який позначається символом $.Транслятор замість цього символа ставить поточне значення вказівника команд і модифікує його значення відповідно до зміщення;

- регістровий операнд – ім’я відповідного регістра, вміст якого використовується у команді;

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

Загальний формат команди показано на рис. 9.10.

Можлива кількість байт
0 – 2 або 4 0 – 2 або 4
Мова програмування Асемблер-86 - student2.ru Код операції Байт режиму адресування Зміщення у команді Безпосередній операнд

Рисунок 9.10 – Загальний формат команди асемблера МП фірми Intel

Байт коду операції – це обов’язковий елемент, що описує операцію, яка буде виконуватися. Складається з поля коду (COP) операції і двох однобітових полів:

– w – відповідає типу операндів, які використовуються у команді:

w = 0 – команда працює з байтами;

w = 1 – команда працює зі словами;

– d – адресує приймач результату:

d = 1 – відбувається передавання операнда або результату операції у регістр rg2, який описано у другому байті команди;

d = 0 – відбувається передавання із цього регістра;

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

 
  Мова програмування Асемблер-86 - student2.ru

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

- md – визначає довжину адреси операнда (у байтах), яка подана у наступних байтах – зміщення у команді:

 
  Мова програмування Асемблер-86 - student2.ru

- COP або rg2 – значення COP використовується для уточнення операції, що виконується; rg2 визначає регістр, в якому знаходиться операнд, який умовно вважається другим;

- rg1 або mem – визначає операнд, який може бути розміщено у комірці пам’яті або у регістрі. Цей операнд умовно вважається першим. Кодування полів rg2 і rg1 в залежності від значення біта s подано у табл. 9.2.

Таблиця 9.2 – Кодування полів rg2 і rg1

rg2 / rg1 w = 0 w = 1 rg2 / rg1 w = 0 w = 1
AL AX AH SP
CL CX CH BP
DL DX DH SI
BL BX BH DI

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

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

1 Який формат має рядок команди мови Асемблер?

2 Що називається операндом у рядку команди мови Асемблер?

3 Які поєднання операндів є можливими?

4 Який формат має команда асемблера МП фірми Intel?

5 В яких байтах може розміщуватися поле коду операції?

6 За допомогою яких бітів кодується тип операндів, що використовуються у команді?

Контрольні питання підвищеної складності:

1 Яким чином визначається тип режиму адресування у команді?

2 За допомогою яких полів визначаються регістри, які використовуються у команді?

3 Доведіть, що операнди команди MOV AX,BX розташовано у регістрах, якщо формат (код) цієї команди становить 89D8Н.

Команди пересилань

Вхідний контроль:

1 Які програмно-доступні вузли МПС Ви знаєте?

2 Яким чином вказується адреса регістрів загального призначення?

3 Які регістри входять до складу центрального процесора?

4 Яким чином може вказуватися адреса комірок пам’яті?

5 Що таке сегментування пам’яті мікропроцесорів фірми Intel?

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

– загальні команди пересилань;

– команди передавання даних з використанням стека (стекові команди);

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

– команди передавання рядків даних;

– команди перетворення типів даних.

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

Загальні команди пересилань –це команди, що здійснюють пересилання операндів: регістр – регістр, регістр – пам’ять, пам’ять – регістр, регістр – безпосередній операнд (число), пам’ять – безпосередній операнд (число).

Найбільш поширеною командою цієї групи є команда MOV (MOVе operand), яка має вигляд

MOV dst,src.

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

Приклади цієї команди при використанні різних способів адресування:

MOV AL,BН ; Пересилання байта з регістра ВН до регістра AL

MOV BX,CX ; Пересилання слова з регістра CX до регістра ВХ

MOV AL,[BX] ; Пересилання байта з комірки пам’яті, адреса якої

; знаходиться у регістрі ВХ, до регістра AL

MOV AХ,[BX] ; Пересилання слова з двох сусідніх комірок

; пам’яті, молодша адреса котрих знаходиться

; у регістрі ВХ, до регістра AХ

Виконання команди MOV AХ,[BX] можливо пояснити таким чином: вважаємо, що до початку виконання цієї команди регістри і комірки пам’яті мали такий вміст:

Вміст регістра (ВХ) = 1234H – базова адреса комірки пам’яті у поточному

сегменті даних.

Вміст регістра (DS) = 7000Н – адреса поточного сегмента даних.

Вміст регістра (AX) – не визначений.

У комірках пам’яті поточного сегмента розміщені байти даних відповідно

 
  Мова програмування Асемблер-86 - student2.ru

Під час виконання операції відбувається копіювання вмісту комірки пам’яті з адресою, що знаходиться у регістрі ВХ, у молодший байт регістра AX – AL і комірки з наступною адресою (1235Н) у старший байт регістра AX – AH. Після виконання цієї команди вміст регістрів буде:

Вміст регістра (ВХ) = 1234H – не зміниться.

Вміст регістра (DS) = 7000Н – не зміниться.

Вміст регістра (AX) = 7856Н – дані, які переслано з пам’яті.

Вміст комірок пам’яті не змінився.

Команда MOVSX (MOVe and Sign eXtension)– пересилання зі знаковим поширенням. Синтаксис команди:

MOVSX dst,src.

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

Як операнди dst (приймач) використовуються 16- або 32-розрядні регістри, а операндом src (джерело) можуть бути 8- або 16-розрядні регістри або комірки пам’яті.

При виконанні команди вміст операнда “джерело” записується, починаючи з молодших розрядів в операнд “приймач”, і знаковий розряд операнда “джерело” поширюється на вільні старші розряди операнда “приймач”.

Наприклад, виконання команди

MOVSX AХ,СL,

якщо до початку її виконання регістри мали такий вміст: (СL) = 82Н, а (AХ) – не визначено, полягає в копіюванні вмісту регістра СL у регістр AL і поширенні знакового розряду у регістрі AH. Після виконання команди у регістрі AХ буде записано операнд FF82H.

Команда MOVZX (MOVe and Zero eXtension)– пересилання з нульовим поширенням. Синтаксис команди:

MOVZX dst,src.

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

Як операнди dst (приймач) використовуються 16- або 32-розрядні регістри, а операндом src (джерело) можуть бути 8- або 16-розрядні регістри або комірки пам’яті.

При виконанні команди, вміст операнда “джерело” записується, починаючи з молодших розрядів в операнд “приймач”, а у старші розряди операнда “приймач” поширюються нулі.

Наприклад, виконання команди

MOVZX AХ,СL,

якщо до її виконання регістри мали такий вміст: (СL) = 82Н, а (AХ) – не визначено, полягає в копіюванні вмісту регістра СL у регістр AL і поширенню нулів у регістрі AH. Після виконання команди у регістрі AХ буде записано операнд 0082H.

Команда XCHG (eXCHanGe)– обмін вмісту операндів. Синтаксис команди:

XCHG dst,src.

Використовується для обміну вмісту 8-, 16-, 32-розрядних регістрів між собою, або для обміну байтами, словами і довгими словами між регістрами і пам’яттю. Команда не працює з сегментними регістрами. Адресування пам’яті може виконуватися будь-яким способом.

Приклади цієї команди при використанні різних способів адресування:

XCHG AL,BН ; Обмін вмісту (байта) регістра ВН на вміст регістра AL

XCHG BX,CX ; Обмін вмісту (слова) регістра CX на вміст регістра ВХ

XCHG AL,[BX] ; Обмін байтом з комірки пам’яті, адреса якої

; знаходиться у регістрі ВХ, і вмістом регістра AL

XCHG AХ,[SI] ; Обмін словом з комірок пам’яті, адреса яких задана

; вмістом регістра SI і словом з регістра АХ.

Команда XLAT (transLATe byte from table) – перетворення байта. Синтаксис команди:

XLAT.

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

Команди LDS/LES/LFS/LGS/LSS (Load pointer into DS/ES/FS/GS/SS segment register)завантаження одного із сегментних регістрів вказівником з пам’яті. Синтаксис команд:

LDS/LES/LFS/LGS/LSSdst,src.

Як операнди dst (приймач) можуть використовуватись 16- або 32-розрядні регістри загального призначення або індексні, а як операнди scr (джерело) – 4 або 8 комірок пам’яті, адресування яких здійснюється довільним способом. Усі команди виконуються однаково, зміни обумовлені регістром, назва якого входить у команду.

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

Виконання однієї з команд, наприклад

LES DI,[SI+2],

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

(DS) = 7000H; (SI) = 1234; DX – не визначено; у комірках пам’яті з адресами 7000:1234 66 77 88 99 АА ВВ СС …

відбувається таким чином:

- вміст комірок пам’яті з адресами 1234+2 і (1234+2)+1 завантажуються у регістр DX. Його вміст стане – 9988Н;

- вміст комірок пам’яті з адресами (1234+2)+3 і (1234+2)+2 завантажуються у регістр ЕS. Його вміст стане – ВВААН.

Команда LЕА (Load Effective Address)– завантаження ефективної адреси. Синтаксис команди:

LЕАdst,src.

Як операнди dst (приймач) можуть використовуватись 16- або 32-розрядні регістри загального призначення або індексні, а як операнд src (джерело) – ефективна адреса, яка обчислюється відповідно заданому режиму адресування. В операнд завантажується значення операнда src (джерело), а не вміст комірки пам’яті, яку він адресує.

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

Команди LDS/LES/LFS/LGS/LSS і LЕА використовуються для ініціалізації регістрів МП перед виконанням обробки рядків даних за допомогою команд обробки рядків. Використання цих команд спрощує комутацію сегментів даних, тому що одночасно завантажується базовий або індексний регістр та сегментний регістр.

Приклад команди завантаження ефективної адреси:

LEA DX,[BX+SI+2] ; Завантаження у регістр DX ефективної адреси,

; значення якої становить суму вмісту регістрів

; BX і SI та числа 2. Якщо вміст регістрів

; (BX) = 0100Н, (SІ) = 0020Н, то у регістрі DX

; після виконання команди буде завантажено

; число 0122Н = 0100Н+0020Н+0002Н

Команда LАHF (Load AH register from register Flags) –завантаження регістра АН ознаками результату із регістра FLAGS. Синтаксис команди:

LАHF.

Команда завантажує копію вмісту молодшого байта регістра Flags, в якому зберігаються 5 ознак – CF, PF, AF, ZF, SF, до 7, 6, 4, 2 і 0 бітів регістра АН.

Команда SАHF (Store AH register into register Flags) –завантаження регістра FLAGS із регістра АН. Синтаксис команди:

SАHF.

Команда відновлює вміст молодшого байта регістра Flags з регістра АН, в якому зберігалися 5 ознак результату – CF, PF, AF, ZF, SF у бітах 7, 6, 4, 2 і 0 відповідно.

Команди LАHF і SАHF використовуються для забезпечення програмної сумісності 8-розрядних МП зі старшими моделями, а також для аналізу стану прапорців і їх зміни за необхідності.

Команди передавання даних з використанням стека (стекові команди) – це команди звернення до стека для завантаження або вивантаження даних. Головна особливість роботи зі стеком – одночасне завантаження/вивантаження двох байтів і автоматична модифікація вмісту регістра вказівника стека SP. До виконання стекових команд необхідно ініціювати регістри SS (регістр сегмента стека) і SP (регістр – вказівник стека).

Команда PUSH (PUSH operand onto stack)– завантаження операнда у стек. Синтаксис команди:

PUSH src.

Як операнд src (джерело) у цій команді можуть бути регістри загального призначення, регістри вказівники, сегментні регістри, комірки пам’яті і безпосередні дані. Довжина операнда становить 2 або 4 байти.

Виконання команди полягає у завантаженні вмісту регістра/комірки пам’яті у дві комірки пам’яті з адресами, що визначаються вмістом регістра SP і становлять, для операндів довжиною 2 байти – (SP)–1 і (SP)–2, причому вміст старшого байта операнда записується у комірку з адресою (SP)–1, а молодшого – у комірку з адресою (SP)–2. Якщо використовуються 4-байтові операнди, значення вказівника стека становлять (SP)–1, (SP)–2, (SP)–3 і (SP)–4. Команду PUSH необхідно використовувати у парі з командою вивантаження POP.

Команда POP (POP operand from the stack)– вивантаження операнда зі стека. Синтаксис команди:

POP dst.

Команда завантажує в операнд dst (приймач) слово або подвійне слово зі стека. Як операнд dst (приймач) у цій команді можуть бути регістри загального призначення, регістри вказівники, сегментні регістри і комірки пам’яті. Довжина операнда становить 2 або 4 байти. Відповідно довжині операнда модифікується вміст регістра SP, який після виконання команди набуває значення (SP)+2 при довжині операнда 2 байти, і становить (SP)+4, якщо довжина операнда становить подвійне слово.

Команда PUSHA (PUSH All general registers onto stack) –завантаження вмісту всіх регістрів загального призначення у стек. Синтаксис команди:

PUSHA.

При виконанні команда розміщує у стеку вміст усіх регістрів загального призначення у наступному порядку: AX, CX, DX, BX, SP, BP, SI, DI. Вміст DI буде розташовано у новій вершині стека (у комірці пам’яті з найменшою адресою). У стеку буде зберігатися вміст регістра SP, що був до початку виконання цієї операції. Значення вказівника стека SP, після виконання команди, буде дорівнювати (SP)–16.

Для роботи з 32-розрядними регістрами загального призначення є команда PUSHAD.

Команда POPA (POP All general registers from the stack)– вивантаження вмісту всіх регістрів загального призначення у стек. Синтаксис команди:

POPA.

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

Для роботи з 32-розрядними регістрами загального призначення є команда POPAD.

Команда PUSHF (PUSH Flags registers onto stack) –завантаження вмісту регістра прапорців у стек. Синтаксис команди:

PUSHF.

Команда POPF (POP Flags registers from the stack)– вивантаження вмісту регістра прапорців у стек. Синтаксис команди:

POPF.

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

Команди введення-виведення– це команди, за допомогою яких можливо обмінюватися даними з периферійними пристроями.

Існують дві команди:

– команда введення IN (INput operand from port). Синтаксис команди:

INdst,src,

де як операнд dst (приймач) використовується вміст акумулятора AL, AX або EAX, а як операнд src (джерело) – адреса (номер) порту у вигляді безпосереднього числа або як вміст регістра DX;

– команда виведення OUT (OUT operand to port).Синтаксис команди

OUTdst,src,

де операнд dst (приймач) – адреса (номер) порту у вигляді безпосереднього числа або як вміст регістра DX, а операнд src (джерело) – акумулятор AL, AX або EAX.

Якщо номер порту задається безпосередньо, то можливо адресувати до 255 портів, а якщо задається вмістом регістра DX, то допускається формування і звернення до 65536 адрес різних портів. Непряме адресування через регістр DX зручно використовувати, якщо адреса порту обчислюється у ході виконання програми.

Команди не змінюють значення регістра прапорців.

Приклади команд введення- виведення:

IN АХ,22Н ; Ведення у регістр АХ слова з порту, номер якого 22Н

IN АL,DX ; Введення у регістр АL байта з порту, номер якого

; завантажено до регістра DX

OUT DX,АХ ; Виведення слова через порт, номер якого завантажено

; до регістра DX

Команди передавання рядків даних –це команди, що дозволяютьобмінюватися даними у вигляді рядків байтів, слів або довгих слів. Рядок – це контекстно-зв’язана послідовність даних, що містяться в суміжних комірках пам’яті. Загалом у системі команд є п’ять операцій, кожна з яких зреалізована трьома командами.

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

MOVSB (MOVe String Byte) –пересилання байтів;

MOVSW (MOVe String Word)– пересилання слів;

MOVSD (MOVe String Double word)– пересилання подвійних слів.

Ці команди копіюють елемент рядок-джерело довжиною байт, слово або подвійне слово, що знаходиться за адресою DS:SI в елемент рядок-приймач, що визначається адресою ES:DI. Адреса операнда-приймача може визначатися тільки регістром ES, заміна адреси операнда-джерела дозволяється, за умовчанням визначено DS.

Після пересилання вміст регістрів SI і DI автоматично змінюється відповідно значення прапорця DF. Якщо прапорець DF дорівнює 0 (була виконана команда CLD), то вміст регістрів SI і DI збільшується, якщо DF має значення 1 (була виконана команда STD), то вміст регістрів SI і DI зменшується. Збільшення/зменшення відбувається на 1, якщо пересилається байт, на 2, якщо пересилається слово, і на 4, якщо пересилається подвійне слово.

Команді може передувати префікс REP, який примушує виконувати пересилання поки вміст регістра СХ не стане дорівнювати 0.

Команди завантаження елемента з рядка в акумулятор AL/AX/EAX мають вигляд:

LODSB (LOad String Byte operands) –завантаження байта;

LODSW (LOad String Word operands)– завантаження слова;

LODSD (LOad String Double word operands)– завантаження подвійного слова.

Ці команди завантажують елемент рядок-джерело довжиною байт, слово або подвійне слово, що знаходиться за адресою DS(ES/GS/FS):SI в акумулятор. Після пересилання вміст регістра SI автоматично змінюється відповідно значення прапорця DF. Якщо прапорець DF дорівнює 0 (була виконана команда CLD), то вміст регістра SI збільшується, якщо DF має значення 1 (була виконана команда STD), то вміст регістра SI зменшується. Збільшення/зменшення відбувається на 1, якщо пересилається байт, на 2, якщо пересилається слово, і на 4, якщо пересилається подвійне слово.

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

Команди збереження вмісту акумулятора AL/AX/EAX у рядку мають вигляд:

STOSB (Store String Byte operands) –завантаження байта;

STOSW (Store String Word operands)– завантаження слова;

STOSD (Store String Double word operands)– завантаження подвійного слова.

Ці команди завантажують дані з акумулятора AL/AX/EAX довжиною байт, слово або подвійне слово у рядок, елемент якого знаходиться за адресою ES:DI. Після пересилання вміст регістра DI автоматично змінюється відповідно значення прапорця DF. Якщо прапорець DF дорівнює 0 (була виконана команда CLD), то вміст регістра DI збільшується, якщо DF має значення 1 (була виконана команда STD), то вміст регістра DI зменшується. Збільшення/зменшення відбувається на 1, якщо пересилається байт, на 2, якщо пересилається слово, і на 4, якщо пересилається подвійне слово.

Команді може передувати префікс REP, що дає можливість формувати блоки пам’яті, кількість елементів у яких буде визначатися вмістом регістра СХ.

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

INSB (INput String Byte operands)– введення рядка байт з порту;

INSW (INput String Word operands) –введення рядка слів з порту;

INSD (INput String Double word operands) –введення рядка подвійних слів з порту.

Ці команди завантажують у пам’ять, адреса якої визначається вмістом регістрів ES:DI, байт, слово або подвійне слово з порту, номер якого задано у регістрі DX. Використовувати у цій команді інші регістри для адресування не дозволяється. Після пересилання вміст регістра DI автоматично змінюється відповідно значення прапорця DF. Якщо прапорець DF дорівнює 0 (була виконана команда CLD), то вміст регістра DI збільшується, якщо DF має значення 1 (була виконана команда STD), то вміст регістра DI зменшується. Збільшення/зменшення відбувається на 1, якщо пересилається байт, на 2, якщо пересилається слово, і на 4, якщо пересилається подвійне слово.

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

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

OUTSB (INput String Byte operands)– виведення рядка байт через порт;

OUTSW (INput String Word operands) –виведення рядка слів через порт;

OUTSD (INput String Double word operands) –виведення рядка подвійних слів через порт.

Ці команди виводять через порт, номер якого задано вмістом регістра DX, дані з пам’яті, яку адресовано регістрами ES:SI, байт, слово або подвійне слово. Дозволяється заміна сегментного регістра для адресування пам’яті. Номер порту може задаватися лише регістром DX. Після пересилання вміст регістра SI автоматично змінюється відповідно до значення прапорця DF. Якщо прапорець DF дорівнює 0 (була виконана команда CLD), то вміст регістра SI збільшується, якщо DF має значення 1 (була виконана команда STD), то вміст регістра SI зменшується. Збільшення/зменшення відбувається на 1, якщо пересилається байт, на 2, якщо пересилається слово, і на 4, якщо пересилається подвійне слово.

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

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

Команда CBW (Convert Byte to Word)– перетворення байта (у регістрі AL) у слово (у регістрі АХ). При виконанні знаковий розряд числа з регістра AL поширюється на всі розряди регістра АН. Наприклад, якщо до виконання команди вміст регістра AL у регістрі АХ був 85Н (число –05 у доповнювальному коді), то після її виконання вміст регістра АХ буде FF85H. Якщо вміст регістра AL був 74Н (число +74Н), то після виконання команди вміст регістра АХ стане 0075Н.

Команда CWD (Convert Word to Double Word) – перетворення слова (у регістрі АХ) у подвійне слово (у регістрах DX:AX). Виконання команди полягає у поширенні знакового розряду з регістра АХ на усі розряди регістра DX.

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

Команда CWDE (Convert Word to Double Word Extended) – перетворення слова (у регістрі АХ) у подвійне слово (у регістрі ЕAX). При виконанні знаковий розряд числа з регістра AХ поширюється на всі старші розряди регістра ЕАХ.

До цієї групи також можливо віднести команди MOVSX i MOVZX, які були розглянуті раніше.

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

1 Які типи команд входять до групи команд пересилань?

2 Чим відрізняється використання команд MOV,MOVSX і MOVZX?

3 Покажіть вміст регістрів DS і BX після виконання команди LDS BX,[1234], якщо комірки пам’яті у поточному сегменті мають вміст: 7000:1234 10 20 30 40 50?

4 Які команди введення-виведення Ви знаєте?

5 Напишіть коментарі з поясненням виконання кожної команди до наступної програми:

MOV CX,0004H ; Завантаження регістра-лічильника

CLD

MOV SI,1234H

REP LODSB

Назвіть вміст регістрів SI і AL після виконання цієї програми, якщо вміст комірок пам’яті у поточному сегменті був такий самий, як у запитанні 3.

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

Контрольні питання підвищеної складності:

1 Яким чином виконується перетворення типів даних зі знаком?

2 Для чого використовується префікс REP?

3 Наведіть вміст регістра – вказівника стека SP і вміст комірок пам’яті з адресами 3456Н і 3455Н після виконання команди PUSH CX, якщо до виконання команди регістри мали вміст: (SP) = 3457Н і (СХ) = 1234Н?

Наши рекомендации