RFLAGS
Le registre RFLAGS - aussi dit registre de drapeaux - est le registre d'état des processeurs de la famille x86-64 (64 bits). Il est compatible avec les registres EFLAGS et FLAGS hérités des familles x86 (32 bits) et précédente (16 bits).
Il permet de fixer et de connaître l'état du processeur à tout moment grâce aux différents bits qui le composent. Ce registre permet ainsi d'avoir à tout instant l'état résultant d'une instruction ayant été exécutée par le processeur, la plupart des instructions des processeurs x86 affectant ce registre.
L'état des différents bits (les drapeaux) du registre RFLAGS permet au processeur de prendre des décisions, par exemple au niveau des branchements conditionnels (sauts et boucles) ou après une opération arithmétique (retenue ou débordement, etc.).
Vue d'ensemble du registre RFLAGS
Le registre RFLAGS est constitué de 64 bits et n'est disponible que sous les processeurs 64 bits (x86-64). Il est toutefois compatible rétroactivement avec les registres EFLAGS (disponible sur les processeurs x86 32 bits) et FLAGS (disponible sur les processeurs 16 et 32 bits). Il se compose comme suit :
- RFLAGS : 64 bits, bits 63 à 0.
- EFLAGS : 32 bits, bits 31 à 0.
- FLAGS : 16 bits, bits 15 à 0.
En cas d'exécution en mode de compatibilité 32 bits (lorsque le processeur 64 bits exécute du code 32 bits) seul EFLAGS et FLAGS sont accessibles.
RFLAGS | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Bits | 63..32 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13..12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
Drapeaux | - | - | - | - | - | - | - | - | - | - | - | ID | VIP | VIF | AC | VM | RF | 0 | NT | IOPL | OF | DF | IF | TF | SF | ZF | 0 | AF | 0 | PF | 1 | CF |
Nota Bene : Les bits 63 à 32, 31 à 22, 15, 5, 3, 1 (en gris sur le tableau) sont des bits réservés, leur utilisation et fonctionnement est inconnu. Les bits 15, 5, 3, 1 ont une valeur fixe donnée dans le tableau ci-dessus.
L'on dit d'un drapeau qu'il est armé lorsqu'il est à 1 et désarmé lorsqu'il est à 0.
Catégories de drapeaux
On distingue trois catégories différentes de drapeaux à l'intérieur du registre RFLAGS.
- Les drapeaux d'état.
- Le drapeau de contrôle.
- Les drapeaux système.
Drapeaux d'état
Les bits 0, 2, 4, 6, 7 et 11 du registre RFLAGS indiquent les résultats d'opérations arithmétiques résultant d'instructions telles que ADD, DIV, MUL, SUB, etc.
- CF (bit 0) Carry Flag (Drapeau de retenue) : Ce drapeau est armé si une opération arithmétique génère une retenue sur le bit le plus significatif (bit de poids fort). Le drapeau est désarmé dans les autres cas. Ce drapeau indique ainsi une condition de débordement en arithmétique entière non signée. Il est aussi utilisé pour l'arithmétique en précision multiple.
- PF (bit 2) Parity Flag (Drapeau de parité) : Armé si l'octet de poids faible (octet le moins significatif) du résultat généré après une opération arithmétique contient un nombre pair de bits à 1. Le drapeau est désarmé dans les autres cas.
- AF (bit 4) Adjust Flag (Drapeau d'ajustement) : Armé si le résultat d'une opération arithmétique génère un résultat provoquant une retenue sur le troisième bit. Le drapeau est désarmé dans les autres cas. Ce drapeau n'est utile que dans l'utilisation du codage BCD.
- ZF (bit 6) Zero Flag (Drapeau zéro) : Armé si le résultat d'une opération arithmétique vaut zéro. Le drapeau est désarmé dans les autres cas.
- SF (bit 7) Sign Flag (Drapeau de signe) : Armé si le résultat d'une opération arithmétique possède un bit de poids fort (bit le plus significatif) à 1, indiquant ainsi un nombre signé négatif. Le drapeau est désarmé dans les autres cas (indiquant possiblement un résultat non signé, c'est-à-dire positif).
- OF (bit 11) Overflow Flag (Drapeau de débordement) : Armé si le résultat constitue un nombre positif ou négatif (en excluant le bit de signe) ne pouvant tenir dans l'opérande de destination. Le drapeau est désarmé dans les autres cas. Ce drapeau indique une condition de débordement pour les opérations arithmétiques signées sur les entiers.
Instructions affectées par les drapeaux d'état
Les instructions conditionnelles suivantes utilisent un ou plusieurs des drapeaux d'état comme condition pour les branchements conditionnels, l'armement d'octets ou les conditions de fin de boucle :
- Jcc : Jump on condition code cc (par exemple les instructions JE, JO, JNC, etc.).
- SETcc : Set on condition code cc (par exemple les instructions SETNE, SETNO, etc.).
- LOOPcc : Loop on condition code cc (par exemple les instructions LOOPE, LOOPNZ, etc.)
- CMOVcc : Conditional move on condition code cc (par exemple les instructions CMOVNZ, CMOVNO, etc.)
Instructions modifiant les drapeaux d'état
Seul le drapeau CF peut être modifié directement via certaines instructions. Ces instructions sont les suivantes :
- CMC (pour Complement Carry Flag) : Inverse l'état du drapeau de retenue.
- CLC (pour Clear Carry Flag): Désarme le drapeau de retenue.
- STC (pour Set Carry Flag) : Arme le drapeau de retenue.
Les instructions suivantes, travaillant sur des bits, peuvent copier un bit spécifique directement dans le drapeau CF :
- BT
- BTC
- BTR
- BTC
Drapeau de contrôle
Le bit 10 du registre RFLAGS est le seul drapeau de contrôle (aussi appelé drapeau de direction).
- DF (bit 10) Direction Flag (Drapeau de direction) : Ce drapeau est utilisé conjointement avec les instructions opérant sur les chaînes de caractères. Lorsque le drapeau DF est armé, les adresses des chaînes de caractères sont auto décrémentées (allant ainsi des adresses les plus hautes vers les adresses les plus basses). Lorsque le drapeau est désarmé, les adresses des chaînes de caractères sont auto incrémentées (allant des adresses les plus basses vers les adresses les plus hautes). Aucun résultat d'opération ne permet d'armer ou de désarmer le drapeau de direction. Seules deux instructions permettent de spécifier explicitement son état.
Instructions affectées par le drapeau de contrôle
Les instructions travaillant sur les chaînes de caractères ou d'octets sont les seules instructions affectées par le drapeau de direction. Ces instructions sont les suivantes :
- CMPS (pour Compare Strings) : Compare deux chaînes.
- LODS (pour Load String) : Charge le prochain mot de la chaîne dans le registre EAX.
- MOVS (pour Move Strings) : Transfère un mot de la chaîne source à la chaîne cible.
- SCAS (pour Scan String) : Compare le mot du registre EAX avec le prochain mot de la chaîne.
- STOS (pour Store String) : Stocke le mot du registre EAX dans le prochain mot de la chaîne.
La taille du mot utilisé par ces instructions est un nombre fixe d'octets dépendant du suffixe utilisé (B pour Byte = 1 octet, W pour Word = 2 octets, D pour Double word = 4 octets...).
Instructions modifiant le drapeau de contrôle
Les instructions permettant de modifier directement le drapeau de direction sont les instructions suivantes :
- CLD (pour Clear Direction Flag) : Désarme le drapeau de direction.
- STD (pour Set Direction Flag) : Arme le drapeau de direction.
Les drapeaux système
Les drapeaux système du registre RFLAGS sont contrôlés par le système d'exploitation ou les opérations de surveillance système. En temps normal un programme applicatif ne devrait pas modifier l'état de ces drapeaux. Les bits 12 et 13 ne sont pas considérés comme deux drapeaux, mais comme un champ de 2 bits (le champ IOPL).
- TF (bit 8) Trap Flag (Drapeau de trappe) : Lorsqu'il est armé, ce drapeau permet le débogage en mode pas à pas, c'est-à-dire instruction par instruction. Lorsqu'il est désarmé, le mode pas à pas est inopérant (fonctionnement normal).
- IF (bit 9) Interrupt Flag (Drapeau d'interruption) : Ce drapeau contrôle la façon dont le processeur répond aux requêtes d'interruptions masquables (c'est-à-dire désactivables). Lorsqu'il est armé, le processeur peut répondre à toutes les interruptions, dans le cas contraire (drapeau IF désarmé), le processeur ne pourra répondre qu'aux interruptions non masquables.
- IOPL (bits 12 et 13) Input / Output privilege level field (Champ de niveau de privilège d'entrée et de sortie) : Ce champ indique le niveau de privilège en entrée/sortie (E/S) du programme ou de la tâche courante. Le niveau de privilège courant du programme ou de la tâche en cours doit être égal ou inférieur au niveau de privilège d'E/S pour accéder à l'espace d'adressage. Ce champ ne peut être modifié qu'avec un niveau de privilège égal à 0 (niveau de privilège le plus haut). Ce concept de niveaux de privilèges est implémenté au travers des anneaux de protection.
- NT (bit 14) Nested task Flag (Drapeau de tâche chaînée) : Ce drapeau contrôle l'enchaînement des tâches interrompues et appelées. Il indique ainsi, lorsqu'il est armé, si la tâche courante est liée à une tâche parent (la tâche qui s'exécutait auparavant) via l'instruction CALL ou par le biais d'une interruption. Lorsqu'il est désarmé, ce drapeau indique simplement que la tâche courante n'a pas de tâche parente.
- RF (bit 16) Resume Flag (Drapeau de redémarrage) : Ce drapeau contrôle la réponse du processeur aux exceptions de débogage. Il assure notamment que le débogage en pas à pas (voir drapeau TF) n'intervient qu'une seule fois par instruction.
- VM (bit 17) Virtual-8086 mode Flag (Drapeau de mode virtuel 8086) : Lorsque ce drapeau est armé le processeur est en mode virtuel 8086. Lorsqu'il est désarmé, le processeur revient en mode protégé.
- AC (bit 18) Alignment Check Flag (Drapeau de vérification d'alignement) : Ce drapeau, lorsqu'il est armé, assure une vérification d'alignement des références mémoire. Lorsqu'il est désarmé, aucune vérification d'alignement n'est effectuée. Ce drapeau nécessite d'armer conjointement le bit AM du registre de contrôle CR0.
- VIF (bit 19) Virtual Interrupt Flag (Drapeau d'interruption virtuelle) : Ce drapeau est une image virtuelle du drapeau IF. Il est utilisé en conjonction avec le drapeau VIP (bit 20).
- VIP (bit 20) Virtual Interrupt Pending Flag (Drapeau d'interruption virtuelle en attente) : Lorsqu'il est armé ce drapeau indique qu'une interruption est en attente. Lorsqu'il est désarmé ce drapeau indique qu'aucune interruption n'est en attente. Seuls les programmes peuvent armer ou désarmer ce drapeau, le processeur ne fait que le lire. À utiliser conjointement avec le drapeau VIF (bit 19).
- ID (bit 21) Identification Flag (Drapeau d'indentification) : Si un programme a la possibilité d'armer ou de désarmer ce drapeau, cela indique que le processeur supporte l'utilisation de l'instruction CPUID.
Instructions affectées par les drapeaux système
D'une manière générale les drapeaux système ne changent pas la manière dont s'exécutent les instructions, ils n'affectent que le fonctionnement général du système d'exploitation. Toutefois, le champ IOPL peut par exemple permettre d'utiliser certaines instructions à différents niveaux de protections.
Instructions modifiant les drapeaux système
Seul le champ IOPL (bits 12 et 13) peut être affecté directement par des instructions. Ces instructions ne sont utilisables que si le niveau de privilège est le plus élevé (niveau 0) :
- IRET
- POPF
Instructions affectant RFLAGS
Outre les instructions permettant d'armer ou de désarmer un seul bit (voire deux pour le champ IOPL) du registre RFLAGS, certaines instructions permettent de lire voir d'écrire tout ou partie du registre RFLAGS. Ces instructions sont :
- LAHF : les bits 0 à 7 de RFLAGS sont mis dans le registre AH (opération de lecture).
- SAHF : le contenu du registre AH est placé dans les bits 0 à 7 de RFLAGS (opération d'écriture).
- POPF : le mot de 16 bits actuellement sur le haut de la pile est placée dans les bits 0 à 15 de RFLAGS (opération d'écriture) - en mode 64 bits, l'instruction nécessite l'operand size prefix (66h) pour opérer sur 16 bits.
- POPFD : le double mot (32 bits) actuellement en haut de la pile est placé dans RFLAGS (opération d'écriture) - en mode 64 bits, l'instruction se comporte comme POPFQ.
- POPFQ : le quadruple mot (64 bits) actuellement en haut de la pile est placé dans RFLAGS (opération d'écriture).
- PUSHF : les bits 0 à 15 de RFLAGS sont poussés sur la pile (opération de lecture) - en mode 64 bits, l'instruction nécessite l'operand size prefix (66h) pour opérer sur 16 bits.
- PUSHFD : le contenu de RFLAGS (32 bits) est poussé sur la pile (opération de lecture) - en mode 64 bits, l'instruction se comporte comme PUSHFQ.
- PUSHFQ : le contenu de RFLAGS (64 bits) est poussé sur la pile (opération de lecture).
Exemple d'utilisation de RFLAGS
N.B : Ces différents codes ne sont exécutables que sur un processeur de la famille x86-64 (64 bits).
Langages C ou C++
- Microsoft Visual C++
#include <iostream>
int main(void)
{
unsigned long long var_RFLAGS = 0;
__asm{
PUSHFQ; // pousse les 64 bits de RFLAGS sur la pile
POP var_RFLAGS; // met RFLAGS dans la variable var_RFLAGS
}
std::cout << std::hex << "Valeur du registre RFLAGS : 0x" << var_RFLAGS;
return 0;
}