Fe23 - довідник x86 - структура машинної команди

Префікси перед кодом операції

Власне команда починається з коду операції. Але перед командою може бути префікс. І навіть відразу кілька префіксів. Кожен префікс - це один байт.

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

Коли перед кодом операції поміщаються префікси, повинні дотримуватися такі два правила:

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

В одній команді не можуть стояти відразу два префікса однієї групи (відразу два префікса команди або відразу два префікса заміни сегмента).

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

Префікс діє тільки в межах тієї команди, перед якою він стоїть.

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

префікси команди

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

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

Код F0 - префікс блокування шини, команда LOCK ( "lock" - замикати). Цей префікс вживається тільки з тими командами, які підтримують таку можливість - можливість блокування шини.

Коди F2. F3 - префікси повторення, команда REP ( "repeat" - повторювати) і інші команди цієї групи. Такі префікси вживаються тільки з ланцюжковими командами. Префікси групи REP дозволяють організувати циклічне виконання цепочечной команди. Дивіться сторінку ланцюгових команд.

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

Дія префікса залежить від конкретної команди.

Префікс зміни розміру операнда

Якщо загальний режим виконання програми дорівнює "32 біта", то для команди, перед якою є префікс 66, встановлюється атрибут розміру операнда "16" біт.

Якщо загальний режим виконання програми дорівнює "16 біт", то для команди, перед якою є префікс 66, встановлюється атрибут розміру операнда "32" бита.

Дія префікса залежить від конкретної команди.

Префікси заміни сегмента

Код 26 - сегмент за умовчанням замінюється на сегмент ES.
Код 2E - сегмент за умовчанням замінюється на сегмент CS.
Код 36 - сегмент за умовчанням замінюється на сегмент SS.
Код 3E - сегмент за умовчанням замінюється на сегмент DS.
Код 64 - сегмент за умовчанням замінюється на сегмент FS.
Код 65 - сегмент за умовчанням замінюється на сегмент GS.

Код операції

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

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

Код операції (скорочено - КОП) може складатися з одного байта або з двох байт. Якщо перший байт коду операції имет значення 0F. то в цьому коді операції є ще й другий байт.

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

В даному довіднику є таблиці команд, в яких команди розташовані в порядку їх кодів операції: Перший байт коду операцій Другої байт коду операцій

У таблицях довідника в колонці "Формат" основний байт коду операції умовно показаний у вигляді восьми рисок, соотвествующих восьми розрядам основного байта.

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

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

Наприклад, позначення (------- w) показує, що в нульовому (самому молодшому) розряді основного байта є особливий біт (w). буква "w" означає "word" - "слово". І це значить, що дана команда має два варіанти, які відрізняються розміром операнда.

Розберемо якийсь конкретний випадок. Нехай це буде команда ADD з кодами 04 та 05, яка виконує операцію складання. Двійковий запис для цих кодів операції виглядає так: 00000100 та 00000101, відмінність тільки в самому молодшому розряді.

Тут варіант команди ADD з кодом 04 (w = 0) виконує операцію складання для байта (розмір операнда 8 біт), а варіант з кодом 05 (w = 1) виконує ту ж операцію для слова (розмір 16 біт).

Але настільки просто все було для 16-бітових процесорів. З появою 32-бітних ситуація ускладнилася. Тепер ця ж команда може виконати свою операцію для байта (8 біт), слова (16 біт), подвійного слова (32 біта). Варіант команди з (w = 0) залишився колишнім, завжди працює тільки для байта (8 біт). Але робота команди в варіанті з (w = 1) буде залежати від встановленого атрибуту розміру операнда, для слова (16 біт) або для подвійного слова (32 біта). Подивіться вище про префікс зміни розміру операнда - код 66, який робить таке перемикання для однієї команди.

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

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

Можна подивитися і з іншого боку, з боку команд асемблера. Якщо для команди INC задається в якості операнда який-небудь регістр, наприклад EAX або EBX, то операнд буде вказано прямо в коді операції машинної команди.

Повний список позначень для особливих бітів і бітових полів основного байта наведено на сторінці Пояснення до основних таблиць.

Байт MRM - (mod, reg, r / m)

Повна назва виглядає саме так - "байт (mod, reg, r / m)". А скорочена назва в різних книгах виглядає по-різному. У нашому довіднику застосовується скорочена назва "байт MRM".

Байт MRM є не у всіх командах. Це визначається конкретним кодом операції (а кажучи точніше, "основним кодом операції"), чи входить байт MRM до складу даної машинної команди або не входить.

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

Байт MRM ділиться на три бітових поля: двухбітовий поле (mod). трехбітовое поле (reg). трехбітовое поле (r / m).

Поле (reg) визначає перший операнд команди, операнд-приймач (destination). Поле (r / m) визначає другий операнд команди, операнд джерело (source). Зазвичай буває саме такий розподіл ролей між (reg) і (r / m). який з операндів буде джерелом, а який приймачем. Але буває і навпаки, це залежить від конкретної команди.

Поле (reg) задає регістр загального призначення. Три біта - це вісім варіантів, вісім різних регістрів.

позначення NNN

В системі команд x86 є такі команди, в яких байт MRM використовується трохи інакше, ніж було описано вище. Відмінність в тому, як трактується поле (reg).

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

Як приклад такого випадку, можна назвати команди з першим байтом коду операції рівним 80. 81. 82. 83. Див. Сторінку Перший байт коду операцій.

У таблицях даного довідника для подібних команд ставиться позначення NNN в колонці "Формат" замість позначення MRM. Просто потрібно було якось виділити окремо цей особливий випадок. Ось і вийшов "байт NNN" замість "байта MRM".

В системі команд x86 є випадки, коли байт MRM застосовується в скороченому вигляді лише через те, що для даної конкретної команди не потрібно, щоб байт MRM ставив два операнда, так як в цій команді потрібен тільки один операнд. У цьому випадку поле (reg) байта MRM просто не використовується, а в документації обмовляється, що завжди має бути (reg = 0).

Таких випадків зовсім небагато:
  • команда MOV, коди C6 і C7
  • команда POP, код 8F
  • група команд SET (cond), коди від 0F 90 до 0F 9F

Для цих випадків у таблицях довідника теж ставиться позначення NNN.

Байт SIB - (scale, index, base)

Байт SIB можливий в команді тільки в режимі 32-розрядний тільки в тому випадку, коли в команді вже є байт MRM (в повній формі або в скороченій формі NNN).

Аналогічно байту MRM, байт SIB ділиться на три бітових поля:

Ці два різні випадки по-різному відображаються в таблицях довідника в колонці "Формат".

безпосередній операнд

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

У таблицях довідника в колонці "Формат" наявність безпосереднього операнда показано позначенням "data (..)". де в дужках вказується кількість байт.

Поле для безпосереднього операнда є не у всіх машинних командах.

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

Всі сторінки довідника

Найостанніші нові сторінки, додані в довідник, можуть бути відсутні в цьому списку. Але все нові сторінки свідомо є в списку на головній сторінці.

Головна сторінка

Основні великі таблиці

Структура машинної команди