Регистр флагов — регистр процессора, отражающий текущее состояние процессора.
В микропроцессорах Intel 8086 имеет название FLAGS и является 16-разрядным. Расширенные регистры EFLAGS и RFLAGS, введённые в архитектурах IA-32 (процессоры 80386) и x86-64, являются 32-битными и 64-битными соответственно. Расширенные регистры сохраняют обратную совместимость.
Регистр флагов содержит группу флагов состояния, управляющий флаг и группу системных флагов[1]:
Регистр флагов Intel x86 | |||||
---|---|---|---|---|---|
Бит, № | Обозначение | Название | Описание | Тип флага | Когда введён |
FLAGS | |||||
0 | CF | Carry Flag | Флаг переноса | Состояние | |
1 | 1 | Зарезервирован | |||
2 | PF | Parity Flag | Флаг чётности | Состояние | |
3 | 0 | ||||
4 | AF | Auxiliary Carry Flag | Вспомогательный флаг переноса | Состояние | |
5 | 0 | Зарезервирован | |||
6 | ZF | Zero Flag | Флаг нуля | Состояние | |
7 | SF | Sign Flag | Флаг знака | Состояние | |
8 | TF | Trap Flag | Флаг трассировки (пошаговое выполнение) | Системный | |
9 | IF | Interrupt Enable Flag | Флаг разрешения прерываний | Системный | |
10 | DF | Direction Flag | Флаг направления | Управляющий | |
11 | OF | Overflow Flag | Флаг переполнения | Состояние | |
12 | IOPL | I/O Privilege Level | Уровень приоритета ввода-вывода | Системный | 80286 |
13 | |||||
14 | NT | Nested Task | Флаг вложенности задач | Системный | 80286 |
15 | 0 | Зарезервирован | |||
EFLAGS | |||||
16 | RF | Resume Flag | Флаг возобновления | Системный | 80386 |
17 | VM | Virtual-8086 Mode | Режим виртуального процессора 8086 | Системный | 80386 |
18 | AC | Alignment Check | Проверка выравнивания | Системный | 80486SX |
19 | VIF | Virtual Interrupt Flag | Виртуальный флаг разрешения прерывания | Системный | Pentium |
20 | VIP | Virtual Interrupt Pending | Ожидающее виртуальное прерывание | Системный | Pentium |
21 | ID | ID Flag | Проверка на доступность инструкции CPUID | Системный | Поздние 80486[2] |
22 | 0 | Зарезервированы | |||
… | |||||
31 | |||||
RFLAGS | |||||
32 | 0 | Зарезервированы | |||
… | |||||
63 |
Значение некоторых флагов в регистре флагов можно изменять напрямую, с помощью специальных инструкций (например, CLD
для сброса флага направления), но нет инструкций, которые позволяют обратиться (проверить или изменить) к регистру флагов как к обычному регистру. Однако, можно сохранять регистр флагов в стек или регистр (E)AX и восстанавливать регистр флагов из них с помощью инструкций LAHF
, SAHF
, PUSHF
, PUSHFD
, POPF
и POPFD
.
При приостановке задачи (используя многозадачные возможности процессора), процессор автоматически сохраняет значение флага регистров в TSS (task state segment), при активизации новой задачи процессор загружает регистр флагов из TSS новой задачи.
Когда активизируется обработчик прерывания или обработчик исключительной ситуации, процессор автоматически сохраняет значение флага регистров в текущем стеке.
Флаги состояния (биты 0, 2, 4, 6, 7 и 11) отражают результат выполнения арифметических инструкций, таких как ADD
, SUB
, MUL
, DIV
.
Из перечисленных флагов только флаг CF можно изменять напрямую с помощью инструкций STC
, CLC
и CMC
. Также, битовые инструкции (BT
, BTS
, BTR
и BTC
) копируют указанный бит во флаг CF.
Флаги состояния позволяют одной и той же арифметической инструкции выдавать результат трёх различных типов: беззнаковое, знаковое и двоично-десятично кодированное (BCD) целое число. Если результат считать беззнаковым числом, то флаг CF показывает условие переполнения (перенос или заём), для знакового результата (в дополнительном коде) перенос или заём показывает флаг OF, а для BCD-результата перенос/заём показывает флаг AF. Флаг SF отражает знак знакового результата, флаг ZF отражает и беззнаковый, и знаковый нулевой результат.
В длинной целочисленной арифметике флаг CF используется совместно с инструкциями сложения с переносом (ADC
) и вычитания с заёмом (SBB
) для распространения переноса или заёма из одного вычисляемого разряда длинного числа в другой.
Инструкции условного перехода Jcc
(переход по условию cc — например, JNZ
для перехода, если результат не ноль), SETcc
(установить значение байта-результата в зависимости от условия cc), LOOPcc
(организация цикла) и CMOVcc
(условное копирование) используют один или несколько флагов состояния для проверки условия. Например, инструкция перехода JLE
(jump if less or equal — переход, если «меньше или равен», ≤) проверяет условие «ZF=1 или SF ≠ OF».
Флаг PF был введён для совместимости с другими микропроцессорными архитектурами и по прямому назначению используется редко. Более распространено его использование совместно с остальными флагами состояния в арифметике с плавающей запятой[3]: инструкции сравнения (FCOM
, FCOMP
и т. п.) в математическом сопроцессоре устанавливают в нём флаги-условия C0, C1, C2 и C3 и эти флаги можно скопировать в регистр флагов. Для этого рекомендуется использовать инструкцию FSTSW AX
для сохранения слова состояния сопроцессора в регистре AX и инструкцию SAHF
для последующего копирования содержимого регистра AH в младшие 8 битов регистра флагов[4], при этом C0 попадает во флаг CF, C2 — в PF, а C3 — в ZF. Флаг C2 устанавливается, например, в случае несравнимых аргументов (NaN или неподдерживаемый формат) в инструкции сравнения FUCOM.
Флаг направления (DF, бит 10 в регистре флагов) управляет строковыми инструкциями (MOVS
, CMPS
, SCAS
, LODS
и STOS
): установка флага заставляет уменьшать адреса (обрабатывать строки от старших адресов к младшим), обнуление заставляет адреса увеличивать. Инструкции STD
и CLD
соответственно устанавливают и обнуляют флаг DF.
Системные флаги и поле IOPL управляют операционной средой и не предназначены для использования в прикладных программах.
IRET
для определения типа возврата — межзадачного или внутризадачного.В поздних версиях процессора 80486 появилась инструкция CPUID, позволяющая идентифицировать процессор, на котором работает программа. В более ранних процессорах для идентификации нужно анализировать особенности поведения инструкций и, в том числе, регистра флагов.
К примеру, в процессорах 8086 и 80186 биты 12-15 регистра флагов всегда установлены, в процессорах 80286 и новее биты 12-14 содержат поле IOPL и флаг NT и в реальном режиме всегда сброшены. Это позволяет в 16-битном коде различать процессоры 808x/8018x, 80286 и 80386 (и новее):
pushf ; (Сохранить исходное состояние регистра флагов)
pushf ; Скопировать регистр флагов...
pop ax ; ...в регистр AX
xor ah,11110000b ; Поменять значение старших 4 битов
push ax ; Скопировать регистр AX
popf ; ...в регистр флагов
pushf ; Скопировать регистр флагов...
pop bx ; ...в регистр BX
popf ; (Восстановить исходное состояние регистра флагов)
xor ah,bh ; AH=0 (биты в регистре флагов не поменялись) → 808x-80286, иначе 80386+
and bh,11110000b ; BH=F0h (все 4 бита установлены) → 808x/8018x, 0 → 80286
Также, флаг AC (бит 18), введённый в 80486, всегда сброшен в 80386, что и позволяет различить эти процессоры:
and sp,not 3 ; Выравнять стек, чтобы не было ошибок выравнивания при обращении к нему
pushfd ; (Сохранить исходное состояние регистра флагов)
pushfd ; Скопировать регистр флагов...
pop eax ; ...в регистр EAX
xor eax,40000h ; Поменять значение бита 18 (флаг AC)
push eax ; Скопировать регистр EAX
popfd ; ...в регистр флагов
pushfd ; Скопировать регистр флагов...
pop ecx ; ...в регистр ECX
popfd ; (Восстановить исходное состояние регистра флагов)
xor eax,ecx ; EAX=0 (бит в регистре флагов не поменялся) → 80386
Аналогично, в старых моделях 80486, где инструкция CPUID
ещё не введена, флаг ID (бит 21) всегда сброшен, что позволяет идентифицировать процессоры 80386 и старые модели 80486:
pushfd ; (Сохранить исходное состояние регистра флагов)
pushfd ; Скопировать регистр флагов...
pop eax ; ...в регистр EAX
mov ecx,eax ; ...и в регистр ECX
or eax,200000h ; Установить бит 21 (флаг ID)
push eax ; Скопировать регистр EAX
popfd ; ...в регистр флагов
pushfd ; Скопировать регистр флагов...
pop eax ; ...в регистр EAX
popfd ; (Восстановить исходное состояние регистра флагов)
xor eax,ecx ; EAX=0 (бит в регистре флагов не устанавливался) → 80386/старые 80486
CPUID
была добавлена в поздних версиях процессора 80486 и процессоре Pentium. См.: CPUID — CPU Identification // The IA-32 Intel Architecture Software Developer’s Manual. — Intel, 2004. — Т. 2A: Instruction Set Reference, A-M. Order number: 253666-013FCOMI
, FCOMIP
и т. п., которые в результате сравнения устанавливают флаги в регистре флагов напрямую. Ранее это было невозможно, поскольку сопроцессор реализовывался отдельной микросхемой, и только начиная с 80486DX сопроцессор начали встраивать в процессор.Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .