Interested Article - Регистр флагов
- 2021-05-05
- 2
Регистр флагов или слово состояния процессора (ССП) — специализированный регистр , отражающий текущее состояние процессора.
Архитектура x86
В микропроцессорах Intel 8086 имеет название FLAGS и является 16-разрядным. Расширенные регистры EFLAGS и RFLAGS, введённые в архитектурах IA-32 (процессоры 80386 ) и x86-64 , являются 32-битными и 64-битными соответственно. Расширенные регистры сохраняют обратную совместимость.
Регистр флагов содержит группу флагов состояния, управляющий флаг и группу системных флагов :
Регистр флагов 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 | Проверка выравнивания | Системный | 80486 SX |
19 | VIF | Virtual Interrupt Flag | Виртуальный флаг разрешения прерывания | Системный | Pentium |
20 | VIP | Virtual Interrupt Pending | Ожидающее виртуальное прерывание | Системный | Pentium |
21 | ID | ID Flag |
Проверка на доступность инструкции
CPUID
|
Системный | Поздние 80486 |
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 — устанавливается при переносе из/заёме в (при вычитании) старший значащий бит результата и показывает наличие переполнения в беззнаковой целочисленной арифметике. Также используется в длинной арифметике .
- PF — устанавливается, если младший значащий байт результата содержит чётное число единичных (ненулевых) битов. Изначально этот флаг был ориентирован на использование в коммуникационных программах: при передаче данных по линиям связи для контроля мог также передаваться бит чётности (см., например: RS-232#Принцип работы ) и инструкции для проверки флага чётности облегчали проверку целостности данных.
- AF — устанавливается при переносе или заёме из бита 4 результата. Этот флаг ориентирован на использование в двоично-десятичной (binary coded decimal, BCD) арифметике.
- ZF — устанавливается, если результат машинной операции по модулю 2 в степени k (где k — разрядность ячейки) равен нулю.
- SF — равен значению старшего значащего бита результата, который является знаковым битом в знаковой арифметике.
- OF — устанавливается, если целочисленный результат слишком длинный для размещения в целевом операнде (регистре или ячейке памяти). Этот флаг показывает наличие переполнения в знаковой целочисленной арифметике (в дополнительном коде ).
Из перечисленных флагов только флаг CF можно изменять напрямую с помощью инструкций
STC
,
CLC
и
CMC
. Также, битовые инструкции (
BT
,
BTS
,
BTR
и
BTC
) копируют указанный бит во флаг CF.
Флаги состояния позволяют одной и той же арифметической инструкции выдавать результат трёх различных типов: беззнаковое, знаковое и двоично-десятично кодированное (BCD) целое число. Если результат считать беззнаковым числом, то флаг CF показывает условие переполнения (перенос или заём), для знакового результата (в дополнительном коде ) перенос или заём показывает флаг OF, а для BCD-результата перенос/заём показывает флаг AF. Флаг SF отражает знак знакового результата, флаг ZF отражает и беззнаковый, и знаковый нулевой результат.
В длинной целочисленной арифметике флаг CF используется совместно с инструкциями сложения с переносом (
ADC
) и вычитания с заёмом (
SBB
) для распространения переноса или заёма из одного вычисляемого разряда длинного числа в другой.
Инструкции условного перехода
J
cc
(переход по условию
cc
— например,
JNZ
для перехода, если результат не ноль),
SET
cc
(установить значение байта-результата в зависимости от условия
cc
),
LOOP
cc
(организация цикла) и
CMOV
cc
(условное копирование) используют один или несколько флагов состояния для проверки условия. Например, инструкция перехода
JLE
(jump if less or equal — переход, если «меньше или равен», ≤) проверяет условие «ZF=1 или SF ≠ OF».
Флаг PF был введён для совместимости с другими микропроцессорными архитектурами и по прямому назначению используется редко. Более распространено его использование совместно с остальными флагами состояния в арифметике с плавающей запятой
: инструкции сравнения (
FCOM
,
FCOMP
и т. п.) в
математическом сопроцессоре
устанавливают в нём флаги-условия C0, C1, C2 и C3 и эти флаги можно скопировать в регистр флагов. Для этого рекомендуется использовать инструкцию
FSTSW AX
для сохранения
слова состояния
сопроцессора в регистре
AX
и инструкцию
SAHF
для последующего копирования содержимого регистра
AH
в младшие 8 битов регистра флагов
, при этом C0 попадает во флаг CF, C2 — в PF, а C3 — в ZF. Флаг C2 устанавливается, например, в случае несравнимых аргументов (NaN или неподдерживаемый формат) в инструкции сравнения FUCOM.
Управляющий флаг
Флаг направления (DF, бит 10 в регистре флагов) управляет строковыми инструкциями (
MOVS
,
CMPS
,
SCAS
,
LODS
и
STOS
): установка флага заставляет уменьшать адреса (обрабатывать строки от старших адресов к младшим), обнуление заставляет адреса увеличивать. Инструкции
STD
и
CLD
соответственно устанавливают и обнуляют флаг DF.
Системные флаги и поле IOPL
Системные флаги и поле IOPL управляют операционной средой и не предназначены для использования в прикладных программах.
- IF — обнуление этого флага запрещает отвечать на маскируемые запросы на прерывание.
- TF — установка этого флага разрешает пошаговый режим отладки , когда после каждой выполненной инструкции происходит прерывание программы и вызов специального обработчика прерывания (см. также: Int3 ).
- IOPL — показывает уровень приоритета ввода-вывода исполняемой программы или задачи: чтобы программа или задача могла выполнять инструкции ввода-вывода или менять флаг IF, её текущий уровень приоритета (CPL) должен быть ≤ IOPL.
-
NT — этот флаг устанавливается, когда текущая задача «вложена» в другую, прерванную задачу, и сегмент состояния TSS текущей задачи обеспечивает обратную связь с TSS предыдущей задачи. Флаг NT проверяется инструкцией
IRET
для определения типа возврата — межзадачного или внутризадачного.
- RF — флаг маскирования ошибок отладки.
- VM — установка этого флага в защищённом режиме вызывает переключение в режим виртуального 8086 .
- AC — установка этого флага вместо с битом AM в регистре CR0 включает контроль выравнивания операндов при обращениях к памяти — обращение к невыравненному операнду вызывает исключительную ситуацию.
- VIF — виртуальная копия флага IF; используется совместно с флагом VIP.
- VIP — устанавливается для указания наличия отложенного прерывания; используется совместно с флагом VIF.
-
ID — возможность программно изменить этот флаг в регистре флагов указывает на поддержку инструкции
CPUID
.
Идентификация процессора
В поздних версиях процессора 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
См. также
Примечания
- 3.4.3. EFLAGS Register // The IA-32 Intel Architecture Software Developer’s Manual. — Intel , 2004. — Т. 1: . Order number: 253665-013
-
↑
Инструкция
CPUID
была добавлена в поздних версиях процессора 80486 и процессоре Pentium. См.: // The IA-32 Intel Architecture Software Developer’s Manual. — Intel , 2004. — Т. 2A: . Order number: 253666-013 - 8.1.3. Branching and Conditional Moves on Condition Codes // The IA-32 Intel Architecture Software Developer’s Manual. — Intel , 2004. — Т. 1: Basic Architecture. Order number: 253665-013
-
В архитектуре
P6
были введены инструкции
FCOMI
,FCOMIP
и т. п., которые в результате сравнения устанавливают флаги в регистре флагов напрямую. Ранее это было невозможно, поскольку сопроцессор реализовывался отдельной микросхемой, и только начиная с 80486DX сопроцессор начали встраивать в процессор.
- 2021-05-05
- 2