Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Yedelev_megapack_VT49V / Интерфейсы периферийных устройств (черновик).doc
Скачиваний:
28
Добавлен:
15.02.2016
Размер:
2.25 Mб
Скачать

Микропроцессор

Регистровая архитектура x86‑совместимых процессоров

Триггер – электронное устройство способное долговременно находиться в двух или более устойчивых состояниях и менять их под воздействием внешних сигналов. Таким образом триггер может использоваться для хранения минимально возможного количества информации - бита.

Регистр – электронное устройство способное хранить небольшой объём цифровой информации и состоящее из триггеров. Количество триггеров в регистре определяет его разрядность, то есть количество бит информации, которое возможно хранить в регистре.

Регистр процессора – блок ячеек памяти, образующий сверхбыструю оперативную память (СОЗУ) ЦП; используется самим ЦП.

В отличие от языков высокого уровня в языке ассемблера переменные хранятся не под абстрактными именами (x, y, z, i, k и т.д.), а непосредственно в регистрах. Поэтому регистры ЦП имеют строго фиксированные имена (и номера) для возможности ссылаться на них из программ на ассемблере (и из машинных команд). Причём имена (номера) имеют не только регистры в целом, но некоторые и их части.

Большинство регистров ЦП недоступны программисту. Соответственно регистры ЦП можно разделить на:

  • Программно доступные – программист может изменять эти регистры по своему усмотрению

  • Программно недоступные (скрытые) – доступ к ним имеет только ЦП, поэтому программист, либо не имеет возможности изменить их, либо может изменять их только косвенным образом.

Некоторые регистры x86‑совместимых процессоров:

  1. Основные регистры

    1. Регистры общего назначения

    2. Сегментные регистры

    3. Регистр флагов (состояния)

    4. Регистр указателя следующей команды

  2. Регистры управления памятью

  3. Регистры управления процессором

  4. Отладочные регистры

  5. Машино‑специфичные регистры

  6. Регистры FPU (Регистры математического сопроцессора)

  7. Регистры MMX/3DNow!

  8. Регистры SSE

  9. Регистры YMM

  10. Прочие регистры

Регистры общего назначения

Хранят операнды арифметических и логических выражений, индексы и адреса, делятся на:

  1. Регистры данных

  2. Регистры индексов

  3. Регистры указателей

Регистры данных

Могут использоваться без ограничений для любых целей, но некоторые команды применяют их специальным образом. Служат для хранения промежуточных вычислений.

  • RAX, EAX, AX, AH, AL – Регистры аккумулятора (Accumulator). Используется для хранения результата арифметических действий.

  • RBX, EBX, BX, BH, BL – Регистры базы (Base). Используются для адресации по базе.

  • RCX, ECX, CX, CH, CL – Регистры счётчика (Counter). Используется для организации циклов и в строковых операциях.

  • RDX, EDX, DX, DH, DL – Регистры данных (Data). Используется для хранения старшей части результата, в том случае если он не помещается полностью в аккумулятор. Может использоваться как адресный регистр при работе с портами ввода‑вывода.

  • R8‑R15, R8D‑R15D, R8W‑R15W, R8B‑R15B – Дополнительные регистры данных появившиеся в 64‑разрядных процессорах.

Структура регистров данных

RAX, RBX, RCX, RDX

EAX, EBX, ECX, EDX

AX, BX, CX, DX

AH, BH, CH, DH

AL, BL, CL, DL

63

32

31

16

15

8

7

0

R8 … R15

R8D … R15D

R8W … R15W

R8B … R15B

63

32

31

16

15

8

7

0

Регистры индексов

Могут использоваться для хранения временных переменных, но только тогда когда не используются по основному назначению. Хранят индексы исходных и целевых элементов массива или строки.

  • RSI, ESI, SI, SIL – Индекс источника (Source Index)

  • RDI, EDI, DI, DIL – Индекс приёмника (Destination Index)

Регистры указателей

Могут использоваться для хранения временных переменных, но только тогда когда не используются по основному назначению. Используются при работе со стеком и при адресации по базе.

  • RBP, EBP, BP, BPL – Указатель базы (Base Pointer)

  • RSP, ESP, SP, SPL – Указатель стека (Stack Pointer)

Структура регистров индексов и указателей

RSI, RDI, RBP, RSP

ESI, EDI, EBP, ESP

SI, DI, BP, SP

SIL, DIL, BPL, SPL

63

32

31

16

15

8

7

0

Регистры SIL, DIL, BPL, SPL появились только в 64‑разрядных процессорах.

Сегментные регистры

Используются для хранения селекторов сегментов.

Селектор сегмента – это некоторое число явным или неявным образом указывающее на положение сегмента в ОП. Например, в реальном режиме селектор сегмента равен адресу начала сегмента делённому на 16 (то есть номеру параграфа) и явно указывает на начало сегмента. А в защищённом режиме - селектор сегмента указывает на ячейку в таблице, расположенной в ОП, в которой и хранится адрес начала сегмента, то есть - указание неявное.

Сегмент – область ОП, в рамках которой можно адресовать данные, указывая смещение (начинающееся с нуля) от начала сегмента, при этом физический (реальный) адрес будет вычисляться ЦП с учётом значения селектора сегмента.

Сегментные регистры имеют разрядность 16 бит и делятся на:

  • CS – Регистр сегмента кода (Code Segment)

  • SS – Регистр сегмента стека (Stack Segment)

  • DS (Data Segment), ES (Extended data Segment), FS, GS – Регистры сегментов данных

Регистр указателя следующей команды

RIP, EIP, IP (Instruction Pointer) – Хранит смещение следующей команды относительно кодового сегмента. Напрямую доступен для записи только в 64‑битных процессорах, но все команды передачи управления осуществляют запись в этот регистр (а также в регистр CS).

Структура регистра указателя следующей команды

RIP

EIP

IP

63

32

31

16

15

0

Регистр флагов

RFLAGS, EFLAGS, FLAGS – Регистр, использующийся при выполнении большинства команд, например: инструкции условного перехода используют один или несколько флагов состояния для проверки условия. В этом регистре каждый бит является флагом, то есть устанавливается в 1 при определенных условиях или установка его в 1 изменяет поведение процессора.

Значение некоторых флагов в регистре флагов можно изменять напрямую, с помощью специальных инструкций, но нет инструкций, которые позволяют обратиться к регистру флагов как к обычному регистру. Однако, можно сохранять регистр флагов в стек или регистр (R/E)AX и восстанавливать регистр флагов из них.

Структура регистра флагов

RFLAGS

EFLAGS

FLAGS

Зарезервированы (всегда 0)

ID

VIP

VIF

AC

VM

RF

0

NT

IOPL

OF

DF

IF

TF

SF

ZF

0

AF

0

PF

1

CF

63

32

31

22

21

20

19

18

17

16

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

  • CF (Carry Flag) – флаг переноса. Устанавливается в 1, если результат предыдущей операции не уместился в приемнике и произошел перенос из старшего бита или если требуется заем (при вычитании), иначе устанавливается в 0. Например, после сложения слова 0FFFFh и 1, если регистр, в который надо поместить результат, — слово, в него будет записано 0000h и флаг CF = 1.

  • PF (Parity Flag) – флаг четности. Устанавливается в 1, если младший байт результата предыдущей команды содержит четное число бит, равных 1; устанавливается в 0, если число единичных бит нечетное. (Это не то же самое, что делимость на два. Число делится на два без остатка, если его самый младший бит равен нулю, и не делится, если он равен 1). Флаг PF был введён для совместимости с другими микропроцессорными архитектурами и по прямому назначению используется редко.

  • AF (Auxiliary Carry Flag) – флаг полупереноса или вспомогательныйфлаг переноса. Устанавливается в 1, если в результате предыдущей операции произошел перенос (или заем) из третьего бита в четвертый. Этот флаг используется автоматически командами двоично-десятичной коррекции.

  • ZF (Zero Flag) – флаг нуля. Устанавливается в 1, если результат предыдущей команды - ноль.

  • SF (Sign Flag) – флаг знака. Этот флаг всегда равен старшему биту результата.

  • TF (Trap Flag) – флаг ловушки (трассировки). Этот флаг был предусмотрен для работы отладчиков, не использующих защищенный режим. Установка его в 1 приводит к тому, что перед выполнением каждой командыгенерируется исключение #DB(прерывание INT 01h) передающее управление отладчику.

  • IF (Interrupt Enable Flag) – флаг разрешенияпрерываний. Сброс этого флага в 0 приводит к тому, что процессор перестает обрабатывать прерывания от внешних устройств. Обычно его устанавливают на короткое время для выполнения критических участков кода.

  • DF (Direction Flag) – флаг направления. Этот флаг контролирует поведение команд обработки строк – когда он установлен в 1, строки обрабатываются в сторону уменьшения адресов, а когда DF = 0 – наоборот.

  • OF (Overflow Flag) – флаг переполнения. Этот флаг устанавливается в 1, если результат предыдущей арифметической операции над числами со знаком выходит за допустимые для них пределы. Например, если при сложении двух положительных чисел получается число со старшим битом, равным единице (то есть отрицательное) и наоборот.

  • IOPL (I/O Privilege Level) –уровень привилегий ввода‑вывода.Показывает уровень привилегий ввода-вывода, с которым выполняется текущая программа или задача: чтобы программа могла обратиться к порту ввода-вывода, ее текущий уровень привилегий (CPL–Current Privilege Level) должен быть ≤ IOPL. Это поле можно модифицировать, только имея нулевой уровень привилегий.

  • NT (Nested Task) –флаг вложенности задач.Равен 1, если текущая задача является вложенной по отношению к какой‑то другой, например: обработчики прерываний и исключений и вызванные командой CALL задачи. Флаг влияет на работу команды IRET.

  • RF (Resume Flag) –флаг маскирования ошибок отладки. Когда этот флаг равен 1, отладочные исключения временно запрещены. Он устанавливается командой IRETD из обработчика отладочного прерывания, чтобы #DB не произошло перед выполнением команды, которая его вызвала, еще раз. На флаг не влияют команды POPF, PUSHF и IRET.

  • VM (Virtual‑8086 Mode) –Режим виртуального процессора 8086. Установка этого флага в защищённом режиме вызывает переключение в режим виртуального 8086. Однако установить этот флаг с помощью непривилегированной команды POPF нельзя.

Режим виртуального процессора 8086 (Режим V86) – подрежим защищённого режима, предназначенный для совместимости с программами разработанными для реального режима. В рамках этого режима процессор ведет себя так, как если бы он находился в реальном режиме, за исключением того, что прерывания и исключения передаются обработчикам защищенного режима вне этой задачи (кроме случая, когда используется карта перенаправления прерываний).

  • AC (Alignment Check) –проверка выравнивания. Если установить этот флаг и флаг AM в регистре управления процессором CR0, каждое обращение к памяти из программ, выполняющихся с CPL = 3, не выровненное на границу слова для слов и на границу двойного слова для двойных слов, будет вызывать исключение #АС.

  • VIF (Virtual Interrupt Flag) –виртуальный флаг разрешения прерывания. Виртуальная копия флага IF; используется совместно с флагом VIP.

  • VIP (Virtual Interrupt Pending) –ожидающее виртуальное прерывание. Этот флаг указывает процессору, что произошло аппаратное прерывание. Флаги VIF и VIP используются в многозадачных средах для того, чтобы каждая задача имела собственный виртуальный образ флага IF.

  • ID (ID Flag) –проверка на доступность инструкции CPUID. Возможность программно изменить этот флаг в регистре флагов указывает на поддержку инструкции CPUID

CPUID (Идентификация процессора) сообщает информацию о производителе, типе и модификации процессора, о наличии и поддержке различных расширений. Команда CPUID поддерживается x86‑совместимыми процессорами, начиная со старших моделей 80486.

Реальный режим адресации

Процессор может находиться в одном из двух режимов работы: режиме реального адреса и режиме виртуального защищенного адреса. Обычно эти режимы называют просто реальным и защищенным. В реальном режиме селекторы сегментов, хранящиеся в сегментных регистрах, равны номеру параграфа, с которого начинается сегмент.

Параграф – единица измерения объёма данных равная 16 байтам. Поскольку размер параграфа, записанный в шестнадцатеричной системе счисления, равен 1016, адрес, кратный параграфу, является круглым числом.

В этом режиме метод генерации линейного адреса прост – селектор сегмента (содержимое сегментного регистра) сдвигается влево на 4 бита (равносильно умножению на 16) и складывается со смещением, в результате чего получается двадцатиразрядный линейный (в данном случае он же - физический) адрес.

Базовый адрес сегмента = Селектор сегмента × 16

Линейный (Физический) адрес = Базовый адрес сегмента + Смещение = = Селектор сегмента × 16 + Смещение

Защищённый режим адресации

В защищенном режиме формирование физического адреса намного сложнее. В этом случае селектор сегмента используется для поиска базового адреса в одной из двух специальных таблиц базовых адресов, находящихся в оперативной памяти. Эти таблицы называются дескрипторными таблицами, или таблицами описания сегментов памяти, так как в них, кроме базовых адресов начала сегментов, содержатся размеры сегментов и байт с описанием прав доступа к этим сегментам.

Одна из них называется глобальной дескрипторной таблицей GDT, а вторая - локальной дескрипторной таблицей LDT. Причём GDT одна для всех задач, выполняемых на компьютере, а LDT может быть своей у каждой задачи и сегмент, в котором она находится, должен быть описан в GDT.

В защищённом режиме селектор сегмента это специальная 16‑битная структура, имеющая следующий вид:

Index

TI

RPL

15

3

2

1

0

Index (биты 15 – 3): номер дескриптора в таблице

TI (бит 2): индикатор таблицы (0 – использовать GDT, 1 – использовать LDT)

RPL (биты 1 – 0): уровень привилегий запроса (Requested Privilege Level). Частным случаем RPL является текущий уровень привилегий – CPL (Current Privilege Level), чьё значение в любой момент времени находится в сегментном регистре CS.

Уровень привилегий запроса (RPL) – это число от 0 до 3, указывающее уровень защиты сегмента, для доступа к которому используется данный селектор. Если программа имеет более высокий уровень привилегий (CPL), при использовании этого сегмента привилегии понизятся до RPL.

Для 32‑битного защищённого режима размер записи в таблицах дескрипторов (размер одного дескриптора) равен 8 байт. Существует несколько типов дескрипторов. Дескриптор сегмента данных или кода имеет следующий вид:

Старшее 32‑разрядное слово дескриптора сегмента

Base (31‑24)

G

D/B

0

AVL

Limit (19‑16)

P

DPL

S

Type

Base (23‑16)

31

24

23

22

21

20

19

16

15

14

13

12

11

8

7

0

Младшее 32‑разрядное слово дескриптора сегмента

Base (15‑0)

Limit (15‑0)

31

16

15

0

G – бит гранулярности. Определяет размер единицы гранулярности:

G = 0, – 1 байт

G = 1, – 4096 байт (4 KiB)

Base – линейный 32‑битный адрес начала сегмента

Limit – 20‑битное число, равное размеру сегмента в единицах гранулярности. Отсчёт ведётся с нуля, так что Limit = 0 соответствует сегменту длиной в одну единицу гранулярности.

Остальные поля определяют тип (Type), права доступа (DPL – Descriptor Privilege Level) и прочие характеристики сегмента

Процессор по селектору, хранящемуся в сегментном регистре, находит соответствующую запись в дескрипторной таблице, считывает значения базового адреса сегмента, добавляет смещение, и полученный результат использует как искомый линейный адрес в оперативной памяти. Однако реально используемый при этом – физический адрес будет получен из линейного путём ещё нескольких преобразований, необходимых в частности для:

  • поддержки процессором более чем 4 GiB (232 байта) памяти в 32‑битном режиме (страничная адресация, режимы PSE‑36 и PAE)

  • поддержки процессором виртуальной памяти, данные которой, при необходимости, могут быть временно выгружены на жёсткий диск

Кэш дескрипторов сегментов (Теневые части сегментных регистров)

Однако если бы процессор всякий раз при генерации физического адреса обращался в оперативную память за базовым адресом сегмента, это привело бы к существенному замедлению его работы. Чтобы предотвратить это разработчики процессора к каждому сегментному регистру добавили теневую часть – кэш дескрипторов сегментов (регистры SDC – Segment Descriptor Cache). При изменении содержимого сегментного регистра процессор из дескрипторной таблицы, хранимой в оперативной памяти, считывает в этот теневой регистр информацию о сегменте, в частности, базовый адрес. И затем для генерации физического адреса используется не значение базового адреса сегмента из дескрипторной таблицы, а его копия, хранимая в теневом регистре внутри процессора. То есть только в том случае, когда мы меняем сегмент на другой, процессор замедляет свою работу по генерации физического адреса. Следовательно, надо стараться реже заменять сегменты при программировании.