Предекодер, ориентируясь на систему команд процессора, анализирует считываемый из памяти код и выделяет в коде поля, относящиеся к отдельным инструкциям. Эти поля для каждой команды определяются согласно формату команды и режимам адресации операндов.
Адресуемые в командах операнды могут храниться в оперативной памяти или регистровой памяти. Адрес операнда, по которому происходит обращение в оперативную или регистровую память называется испольнительным адресом. Информация из адресной части команды называется адресным кодом.
В общем случае испольнительный адрес рассчитывается из полей, содержащихся в адресном коде. Способ получения исполнительного адреса операнда из адресного кода называется режимом адресации операнда.
В современных вычислительных системах используется множество различных режимов адресации. Для обобщения используется следующая классификация:
По наличию адресной информации в команде:
По кратности обращения (R) в память:
По способу формирования исполнительного адреса.
При относительной регистрации в Intel исполнительный адрес (АИ) формируется по следующей формуле:
АИ = Base + Index * Scale + Disp, где
Base - содержимое базового регистра
Index * Scale - содержимое индексного регистра, умноженного на масштабный множитель
Disp - 8-, 16-, 32-разрядной смещение, заданное в команде.
Такая схема адресации удобна при многократном обращении в программе к различным элементам одного массива. Можно в команде напрямую указать неизменный адрес начала массива (Displacement), а адрес строки в массиве и адрес столбца в строке указать косвенно через регистр-базу и регистр-индекс, размер элемента можно указать в масштабном множителе. Изменяя содержимое базового и индексного регистра можно перебрать все элементы массива не меняя команду обращения.
В некоторых командах база явно не указывается, но подразумевается. Так, например, в командах J и LOOP базой считается адрес следующей команды из регистра EIP, а смещение храниться в команде.
Стековая память является эффективным элементом современных ЭВМ, реализует неявное задание адреса операнда. Хотя адрес обращения в стек отсутсвует в команде, он формируется схемой управления автоматически по специальному правилу.
Стек представляет собой группу последовательно пронумерованных регистров (аппаратный стек) или ячеек памятти (программный стек), снабженных указателем стека (обычно счетчиком адреса (СЧА)). В СЧА автоматически при записи и считывании устанавливается номер (адрес) первой свободной ячейки стека (вершина стека).
Таким образом, в стеке реализуется принцип LIFO "последний пришел - первый ушел".
В отличие от MIPS, команды архитектуры x86-64 вдобавок к точно определяющим инструкцию битам (opcode) также могут содержать в себе префиксы и встроенные в инструкцию данные. Таким образом, команды могут занимать от 2 до 16 байт.
Сами инструкции можно разбить на три типа:
В таблице 1 представлен общий формат инструкций.
Таблица 1. Формат инструкций архитектуры x86-64.
Общие префиксы |
Префиксы расширения |
Opcode |
Mod R/M |
SIB |
Displacement |
Immediate |
0-4 байта |
0-4 байта |
1-3 байта |
0-1 байт |
0-1 байт |
0-4 байта |
0-4 байта |
В общем случае команду можно разбить на две части:
Ниже представлено подробное описание каждого из полей.
Префикс - особый однобайтный код, которые позволяют уточнить поведение команды. В каждой инструкции может содержаться до 4 префиксов общего назначения.
Условно префиксы можно разделить на четыре группы:
Префиксы блокировки: инициируют выдачу сигнала блокировки системной шины во время выполнения текущей команды.
Префиксы повторения: используются для работы со строковыми командами. Они организуют цикл повторения строковой команды до окончания просмотра строки-источника или до выполнения какого-либо условия.
Префиксы выбора сегментного регистра: позволяют использовать альтернативный сегментный регистр взамен используемого по умолчанию.
Префикс переопределения размеров операндов или адреса: позволяют на время выполнения команды изменить разрядность машинного слова или адреса памяти.
Ситуация, когда в команде присутствует два и более префикса из одной группы, не определено и по-своему обрабатывается на различных процессорах.
Префиксы расширения используются для процессоров новых поколений с различными расширениями, одна инструкция может содержать только один префикс расширения или не содержать его вообще. Префиксы расширения имеют следующие типы:
Код операции определяет выполняемые процессором действия (сложение, сдвиг, изменение режима работы процессора) по текущей команде.
Mod_R/M – используется для адресации операндов. Может отсутствовать в кодировке, если инструкция не имеет явных операндов. Состоит из трех информационных полей Mod, R/M и Reg:
В некоторых случаях для того, чтобы полностью определить форму адресации используется байт SIB и 1-4 байта смещения.
SIB (Scale index base) – второй байт, использующийся для адресации операндов в памяти. Может отсутствовать. Включает в себя следующие поля:
3-битовые поля Index и Base определяют выбор регистров, используемых в качестве индексного и базового регистров, и 2-битовое поле Scale, задающее масштабный множитель для значения индекса. Допускается только 4 значения масштабного множителя: умножение на 1 - код 00, умножение на 2 - код 01, на 4 - код 10, на 8 - код 11.
Displacement – байт смещения.
Immediate - константа
Каждая команда проходит в процессоре несколько фаз обработки:
Регистр флагов EFLAGS предназначен для хранения признака результата выполненной операции (получен ли ноль, отрицательное число, был ли перенос из числового в знаковый разряд при двоичном вычислении, было ли переполнение и т.д.) Эти флаги используются некоторыми командами (такими, например, как J** и CMP) для проверки условий и организации ветвления в программе. В таблице 2 показана структура регистра EFLAGS.
Таблица 2. Структура регистра EFLAGS.
31...22 |
21 |
20 |
19 |
18 |
17 |
16 |
15 |
14 |
13,12 |
11 |
000...000 |
ID |
VIP |
VIF |
AC |
VM |
RF |
0 |
NT |
IOPL |
OF |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
DF |
IF |
TF |
SF |
ZF |
0 |
AF |
0 |
PF |
1 |
CF |
В таблице 3 показано назначение каждого из флагов:
Таблица 3. Назначение флагов.
Название флага | Назначение флага |
CF (Carry flag) | Флаг переноса. Устанавливается в 1, если в результате выполнения операции был перенос из старшего разряда. |
PF (Parity flag) | Флаг паритета. Устанавливается в 1, если младшие 8 бит результата операции содержат четное число двоичных единиц. |
AF (Auxiliary flag) | Флаг вспомогательного переноса. Устанавливается в 1, если произошел перенос в старшую тетраду (первые 4 бита). Используется в операциях над упакованными двоично-десятичными числами. |
ZF (Zero flag) | Флаг нуля. Устанавливается в 1, если результат операции равен 0. |
SF (Sign flag) | Флаг знака. Устанавливается в 1, если результат операции отрицательный. |
TF (Trace flag) | Управляющий флаг трассировки. Если этот флаг установить в 1, то после выполнения каждой команды управление временно передается отладчику. |
IF (Interrupt flag) | Управляющий флаг разрешения прерываний. Если сбросить этот флаг в 0, то процессор перестанет обрабатывать прерывания от внешних устройств. Обычно его сбрасывают на короткое время для выполнения критических участков программы. |
DF (Direction flag) | Флаг направления. Контролирует поведение команд обработки строк. Если установлен в 1, то строки обрабатываются в сторону уменьшения адресов, если сброшен в 0, то наоборот. |
OF (Overflow flag) | Флаг переполнения. Фиксирует выход результата за пределы допустимого для данного процессора диапазона значений. |
IOPL (Input/Output Privilege level) | Двухразрядное поле привелегий указывает на максимальное значение уровня текущего приоритета, при котором команды ввода-вывода выполняются без генерации исключительной ситуации. |
NT (Nested task) | Флаг вложенной задачи. Создан для контроля за прерванными задачами и при вызове процедур. |
RF (Restart flag) | Управляющий флаг возобновления. |
VM (Virtual mode) | Управляющий флаг виртуального режима. Используется для перевода процессора в режим виртуального процессора 8086. |
AC (Alignment check) | Флаг контроля выравнивания, при установленном флаге, при исполнении программ с уровнем привилегии 3, при обращении к операнду, который не выровнен по соответсвующей границе (2, 4, 8 байт) произойдет исключение #AC. |
VIF (Virtual interrupt flag) | Флаг разрешения прерывания для многозадачных систем. |
VIP (Virtual interrupt pending) | Виртуальный запрос прерывания. |
ID (ID flag) | Флаг доступности команды идентификатора CPUID. |