Архитектура 32-битных микропроцессоров семейства Intel IA-32. Часть 1
Регистры
Программная модель включает восемь регистров общего назначения, шесть регистров сегментов, указатель команд, регистр системных флагов, регистры системных адресов, четыре регистра управления и шесть регистров отладки.
Восемь регистров общего назначения имеют длину в 32 бит и содержат адреса или данные. Они поддерживают операнды-данные длиной 1, 8, 16, 32 и (при использовании двух регистров) 64 бит; битовые поля от 1 до 32 бит; операнды-адреса длиной 16 и 32 бит. Эти регистры называются EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP. Доступ к младшим 16 бит этих регистров выполняется независимо при использовании соответствующих имен 16-битных регистров: AX, BX, CX, DX, SI, DI, BP и SP. Также могут использоваться индивидуально младший (биты 0-7) и старший (биты 8-15) байты регистров AX, BX, CX, DX. Им соответствуют обозначения AH, DH, CH, BH и AL, DL, CL, BL.
Хотя регистр ESP тоже относится к регистрам общего назначения, он содержит указатель на вершину стека и не используется для других целей.
Следует отметить, что регистры могут быть неравнозначны и при использовании определенных инструкций могут иметь специальное значение:
- EAX - аккумулятор, операнд-источник или приемник результата (некоторые инструкции могут быть короче на один байт при использовании EAX);
- EBX - указатель на данные в сегменте DS;
- ECX - счетчик для цепочечных (например, MOVS) и циклических (с префиксом REP) инструкций;
- EDX - адрес порта ввода-вывода для инструкций IN/INS, OUT/OUTS;
- ESI - указатель на операнд-источник в сегменте DS для цепочечных инструкций;
- EDI - указатель на операнд-приемник в сегменте ES для цепочечных инструкций;
- EBP - указатель на данные в сегменте SS.
МП включает шесть непосредственно доступных 16-битных регистров сегментов. С каждым сегментным регистром ассоциирован программно-недоступный кэш дескриптора соответствующего сегмента, содержащий базовый адрес сегмента в линейном адресном пространстве, предел сегмента и атрибуты сегмента. Этот кэш заполняется при загрузке значения в сегментный регистр. В реальном режиме предел сегмента всегда 0FFFFh, атрибуты игнорируются, а базовый адрес вычисляется сдвигом значения селектора на 4 бита влево. В защищенном режиме кэш заполняется соответствующими значениями из дескрипторной таблицы.
Не все сегментные регистры равнозначны. Регистр CS хранит селектор сегмента кода. МП извлекает очередную инструкцию для исполнения, формируя логический адрес из селектора в CS и смещения в регистре EIP. Значение этого регистра нельзя изменить непосредственно, оно меняется в командах межсегментного перехода (FAR JMP), межсегментного вызова (FAR CALL), при вызове обработчика прерывания (INT) и при возврате из далекой процедуры (RETF) или обработчика прерывания (IRET).
Регистр SS хранит селектор сегмента стека. Стек используется для передачи параметров подпрограммам и для сохранения адреса возврата при вызове подпрограммы или обработчика прерывания. Вершиной стека считается байт, логический адрес которого образуется из селектора в регистре SS и смещения в регистре ESP. Программа может непосредственно изменить значение SS, что дает ей возможность переключаться между несколькими стеками. Причем на время выполнения команды MOV SS,xxxx и одной команды, следующей за ней (обычно это MOV ESP,xxxx), запрещаются маскируемые и блокируются немаскируемые прерывания.
Регистры DS, ES, FS и GS хранят селекторы сегментов данных. Если инструкция обращается к памяти, но содержит только смещение, то считается, что она обращается к данным в сегменте DS. Сегмент ES может использоваться без явного указания в цепочечных командах. Сегменты FS и GS используются при обращении к памяти только при явном использовании в инструкции префиксов этих сегментов.
Указатель команд (EIP) является 32-разрядным регистром. Он содержит смещение следующей команды, подлежащей выполнению. Относительный адрес отсчитывается от базового адреса сегмента исполняемой задачи. Указатель команд непосредственно недоступен программисту, но он изменяется явно командами управления потоком, прерываниями и исключениями (JMP, CALL, RET, IRET, команды условного перехода). Получить текущее значение EIP можно, если выполнить команду CALL, а затем прочитать слово на вершине стека.
Регистр системных флагов EFLAGS содержит группу флагов состояния, управления и системных флагов. Младшие 16 бит регистра представляют собой 16-разрядный регистр флагов и состояния МП 8086, называемый FLAGS, который наиболее полезен при исполнении программ для МП 8086 и Intel-286. Некоторые из флагов могут быть изменены специально предназначенными для этой цели инструкциями. Для изменения или проверки группы флагов можно воспользоваться следующими командами:
- LAHF/SAHF - загрузка/сохранение младших 8 битов регистра флагов в регистре AH;
- PUSHF/POPF - помещение/извлечение из стека младших 16 битов регистра флагов;
- PUSHFD/POPFD - помещение/извлечение из стека 32-битного регистра EFLAGS.
Регистры управления сегментированной памятью, известные также как регистры системных адресов, указывают на структуры данных, которые управляют механизмом сегментированной памяти. Они определены для ссылок на таблицы или сегменты, поддерживаемые моделью защиты МП.
- Регистр глобальной дескрипторной таблицы (GDTR). Содержит 32-битный линейный адрес и 16-битную границу глобальной дескрипторной таблицы. Значение этого регистра можно загрузить/сохранить при помощи привилегированных инструкций LGDT/SGDT. В реальном режиме этот регистр не используется. Перед переходом в защищенный режим в этот регистр следует загрузить корректные значения.
- Регистр локальной дескрипторной таблицы (LDTR). Содержит 16-битный селектор локальной дескрипторной таблицы. С регистром связан программно-недоступный кэш дескриптора для хранения базового адреса, предела и атрибутов соответствующей дескрипторной таблицы. Значение этого регистра можно загрузить/сохранить при помощи привилегированных инструкций LLDT/SLDT. В реальном режиме этот регистр не используется, и попытка обращения к нему генерирует особый случай "недействительный код операции" (исключение #6). С каждой задачей в защищенном режиме может быть связана своя локальная дескрипторная таблица, поэтому селектор LDT хранится в TSS и автоматически загружается при переключении задач.
- Регистр таблицы дескрипторов прерываний (IDTR). Указывает на таблицу точек входа в программы обработки прерываний. Регистр содержит 32-битный линейный базовый адрес и 16-битный предел таблицы. Значение этого регистра можно загрузить/сохранить при помощи привилегированных инструкций LIDT/SIDT. При инициализации МП базовый адрес IDT устанавливается в 0, а предел - 0FFFFh. В реальном режиме эта таблица хранит 4-байтные векторы прерываний, а в защищенном - 8-байтные дескрипторы шлюзов обработчиков прерываний и исключений. Это единственный регистр среди перечисленных, который используется в реальном режиме.
- Регистр задачи (TR). Указывает на информацию, необходимую МП для определения текущей задачи. Регистр содержит 16-битный селектор дескриптора сегмента состояния задачи. С регистром связан программно-недоступный кэш дескриптора TSS для хранения базового адреса, предела и атрибутов соответствующего сегмента состояния задачи. Значение этого регистра можно загрузить/сохранить при помощи привилегированных инструкций LTR/STR. В реальном режиме этот регистр не используется, и попытка обращения к нему генерирует особый случай "недействительный код операции" (исключение #6).
МП имеет четыре 32-разрядных регистра управления CR0-CR4, в которых хранятся флаги состояния МП или глобальные флаги. Вместе с регистрами системных адресов эти регистры хранят информацию о состоянии МП, которая влияет на все задачи в системе. Системным программистам регистры управления доступны только через варианты команды MOV, которые позволяют их загружать или сохранять в регистрах общего назначения.
Шесть доступных регистров отладки (DR0-DR3, DR6, DR7, регистры DR4 и DR5 зарезервированы) расширяют возможности отладки. Они устанавливают точки останова по данным и позволяют устанавливатьзадавать точки останова по командам без модификации сегментов программ. Регистры DR0-DR3 предназначены для хранения четырех линейных адресов точек останова. Регистр DR6 отражает текущее состояние точек останова. Регистр DR7 задает условие для точек останова.
В МП Intel-386 и Intel-486 использовались также 2 регистра страничных проверок (TR6 и TR7), которые позднее были исключены из архитектуры IA-32.
Формат команды микропроцессора IA-32
Инструкция микропроцессора может содержать следующие поля:
префикс | КОП | Mod R/M | SIB | смещение | непосредственный операнд |
---|---|---|---|---|---|
0/1 байт | 1/2 байта | 0/1 байт | 0/1 байт | 0/1/2/4 байта | 0/1/2/4 байта |
Префикс - необязательная часть инструкции, которая позволяет изменить некоторые особенности ее выполнения. В команде может быть использовано сразу несколько префиксов разного типа. Типы префиксов: командные префиксы (префиксы повторения) REP, REPE/REPZ, REPNE/REPNZ; префикс блокировки шины LOCK; префиксы размера; префиксы замены сегмента.
Байт "Mod R/M" определяет режим адресации, а также иногда дополнительный код операции. Необходимость байта "Mod R/M" зависит от типа инструкции.
Байт SIB (Scale-Index-Base) определяет способ адресации при обращении к памяти в 32-битном режиме. Необходимость байта SIB зависит от режима адресации, задаваемого полем "Mod R/M".
Кроме того, инструкция может содержать непосредственный операнд и/или смещение операнда в сегменте данных.
На размер инструкции накладывается ограничение в 15 байт. Инструкция большего размера может получиться при некорректном использовании большого количества префиксов. В IA-32 в таком случае генерируют исключение #13.
Если инструкция микропроцессора требует операнды, то они могут задаваться следующими способами: непосредственно в коде инструкции (только операнд-источник); в одном из регистров; через порт ввода-вывода; в памяти.
Для совместимости с 16-битными процессорами архитектура IA-32 использует одинаковые коды для инструкций, оперирующих как с 16-битными, так и 32-битными операндами. Новая архитектура предусматривает также новые возможности при указании адреса для операнда в памяти. Как процессор будет считать операнд или его адрес, зависит от эффективного размера операнда и эффективного размера адреса для данной команды. Эти значения определяются на основе режима работы, бита D дескриптора используемого сегмента и наличия в инструкции определенных префиксов.
Непосредственный режим адресации подразумевает включение операнда-источника в код инструкции. Операнд может быть 8-битовым или 16-битовым, если значение эффективного размера операнда - 16. Операнд может быть 8-битовым или 32-битовым, если значение эффективного размера операнда - 32. Обычно непосредственные операнды используются в арифметических инструкциях.
Регистровый режим адресации определят операнд-источник или операнд-приемник в одном из регистров процессора или сопроцессора.
В некоторых случаях, (например, в инструкциях DIV и MUL) могут использоваться пары 32-битных регистров (например, EDX:EAX), образуя 64-битный операнд.
Адресация через порт ввода-вывода подразумевает получение операнда или сохранение операнда через пространство портов ввода-вывода. Адрес порта ввода-вывода либо непосредственно включается в код инструкции, либо берется из регистра DX.
Очень распространенный способ адресации операнда - адресация через память. Таким образом, может быть указан операнд-источник или операнд-приемник. Следует отметить, что процессор не позволяет одновременно задавать оба операнда через память (за исключением некоторых цепочечных команд).
Для получения операнда из памяти процессору необходимо знать селектор сегмента и смещение в сегменте. В некоторых командах селектор может быть указан непосредственно в коде инструкции. В других случаях процессор может явно или неявно использовать значение одного из сегментных регистров. Под неявным использованием сегментных регистров подразумевается то, что в зависимости от предназначения операнда процессор использует определенный сегментный регистр для обращения к памяти: CS -для выборки инструкций; SS - для работы со стеком или обращения к памяти через регистры ESP или EBP; ES - для получения адреса операнда-приемника в цепочечных командах; DS - при всех остальных обращениях к памяти. Явное использование сегментных регистров возможно, если в код инструкции включается префикс смены сегмента. Указание префикса смены сегмента допустимо не для всех команд: нельзя менять сегмент для команд работы со стеком (всегда используется SS); для цепочечных команд можно менять сегмент только операнда-источника (операнд-приемник всегда адресуется через ES).
Смещение в сегменте (эффективный или исполнительный адрес - EA) может быть вычислено на основе значений регистров общего назначения и/или указанного в коде инструкции относительного смещения, при этом любой или даже несколько из указанных компонентов могут отсутствовать:
EA = BASE + (INDEX*SCALE) + DISPLACEMENT
Такая схема позволяет в языках высокого уровня и на языке Ассемблера легко реализовать работу с массивами.