Architecture x86
Le processeur Intel x86 utilise une architecture CISC (Jeu d’instructions complexes), ce qui signifie qu’il existe un nombre modeste de registres à usage spécial au lieu de grandes quantités de registres à usage général. Cela signifie également que les instructions complexes à usage spécial prédomineront.
Le processeur x86 trace son héritage au moins aussi loin que le processeur Intel 8080 8 bits. De nombreuses particularités dans le jeu d’instructions x86 sont dues à la compatibilité descendante avec ce processeur (et avec sa variante Zilog Z-80).
Microsoft Win32 utilise le processeur x86 en mode plat 32 bits. Cette documentation se concentre uniquement sur le mode plat.
Registres
L’architecture x86 se compose des registres d’entiers non privilégiés suivants.
Eax |
Accumulateur |
Ebx |
Registre de base |
ecx |
Registre de compteurs |
Edx |
Registre de données : peut être utilisé pour l’accès au port d’E/S et les fonctions arithmétiques |
Esi |
Registre d’index source |
Edi |
Registre d’index de destination |
Ebp |
Registre des pointeurs de base |
Esp |
Pointeur de pile |
Tous les registres d’entiers sont de 32 bits. Toutefois, la plupart d’entre eux ont des sous-inscriptions 16 bits ou 8 bits.
ax |
Faible 16 bits d’eax |
Bx |
Faible 16 bits d’ebx |
Cx |
Faible 16 bits d’ecx |
Dx |
Faible 16 bits d’edx |
si |
Faible 16 bits d’esi |
Di |
Faible 16 bits d’edi |
Bp |
Faible 16 bits d’ebp |
sp |
Faible 16 bits d’esp |
Al |
Faible 8 bits d’eax |
Ah |
Haute 8 bits de hache |
Bl |
Faible 8 bits d’ebx |
Bh |
High 8 bits de bx |
Cl |
Faible 8 bits d’ecx |
ch |
High 8 bits de cx |
Dl |
Faible 8 bits d’edx |
Dh |
High 8 bits de dx |
Le fonctionnement d’une sous-inscription affecte uniquement la sous-inscription et aucune des parties en dehors de la sous-inscription. Par exemple, le stockage dans le registre ax laisse les 16 bits élevés du registre eax inchangés.
Lors de l’utilisation de ? (Évaluer l’expression) commande , les registres doivent être précédés d’un signe « at » ( @ ). Par exemple, vous devez utiliser ? @ax plutôt que ? ax. Cela garantit que le débogueur reconnaît ax comme un registre plutôt qu’un symbole.
Toutefois, le (@) n’est pas obligatoire dans la commande r (Registres). Pour instance, r ax=5 sera toujours interprété correctement.
Deux autres registres sont importants pour l’état actuel du processeur.
Eip |
pointeur d’instruction |
flags |
flags |
Le pointeur d’instruction est l’adresse de l’instruction en cours d’exécution.
Le registre des indicateurs est une collection d’indicateurs mono bits. De nombreuses instructions modifient les indicateurs pour décrire le résultat de l’instruction. Ces indicateurs peuvent ensuite être testés par des instructions de saut conditionnel. Pour plus d’informations, consultez Indicateurs x86 .
Conventions d’appel
L’architecture x86 a plusieurs conventions d’appel différentes. Heureusement, ils suivent tous les mêmes règles de conservation de registre et de retour de fonction :
Les fonctions doivent conserver tous les registres, à l’exception de eax, ecx et edx, qui peuvent être modifiés dans un appel de fonction, et esp, qui doivent être mis à jour conformément à la convention d’appel.
Le registre eax reçoit des valeurs de retour de fonction si le résultat est inférieur ou égal à 32 bits. Si le résultat est de 64 bits, le résultat est stocké dans la paire edx :eax .
Voici la liste des conventions d’appel utilisées sur l’architecture x86 :
Win32 (__stdcall)
Les paramètres de fonction sont transmis sur la pile, poussés de droite à gauche, et l’appelé nettoie la pile.
Appel de méthode C++ natif (également appelé thiscall)
Les paramètres de fonction sont transmis sur la pile, poussés de droite à gauche, le pointeur « this » est passé dans le registre ecx et le appelé nettoie la pile.
COM (__stdcall pour les appels de méthode C++)
Les paramètres de fonction sont transmis sur la pile, envoyés de droite à gauche, puis le pointeur « this » est envoyé sur la pile, puis la fonction est appelée. L'appelé nettoie la pile.
__fastcall
Les deux premiers arguments DWORD ou plus petits sont passés dans les registres ecx et edx . Les paramètres restants sont transmis sur la pile, poussés de droite à gauche. L'appelé nettoie la pile.
__cdecl
Les paramètres de fonction sont transmis sur la pile, poussés de droite à gauche, et l’appelant nettoie la pile. La convention d’appel __cdecl est utilisée pour toutes les fonctions avec des paramètres de longueur variable.
Affichage des registres et des indicateurs du débogueur
Voici un exemple d’affichage du registre du débogueur :
eax=00000000 ebx=008b6f00 ecx=01010101 edx=ffffffff esi=00000000 edi=00465000
eip=77f9d022 esp=05cffc48 ebp=05cffc54 iopl=0 nv up ei ng nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000286
Dans le débogage en mode utilisateur, vous pouvez ignorer l’iopl et la dernière ligne entière de l’affichage du débogueur.
Indicateurs x86
Dans l’exemple précédent, les codes à deux lettres à la fin de la deuxième ligne sont des indicateurs. Il s’agit de registres mono bits qui ont diverses utilisations.
Le tableau suivant répertorie les indicateurs x86 :
Code d’indicateur | Nom de l’indicateur | Valeur | État de l’indicateur | Description |
---|---|---|---|---|
sur | Indicateur de dépassement de capacité | 0 1 | nvov | Aucun dépassement de capacité - Dépassement de capacité |
df | Balise de direction | 0 1 | updn | Direction vers le haut - Direction vers le bas |
if | Indicateur d’interruption | 0 1 | diei | Interruptions désactivées - Interruptions activées |
sf | Indicateur de signe | 0 1 | plng | Positif (ou zéro) - Négatif |
Zf | Zéro indicateur | 0 1 | nzzr | Non zéro - Zéro |
af | Indicateur de transport auxiliaire | 0 1 | naac | Pas de transport auxiliaire - Transport auxiliaire |
Pf | Indicateur de parité | 0 1 | Pepo | Parité impaire - Parité pair |
Cf | Indicateur de transport | 0 1 | nccy | Pas de transport - Transport |
Tf | Indicateur d’interruption | Si tf est égal à 1, le processeur déclenche une exception STATUS_SINGLE_STEP après l’exécution d’une instruction. Cet indicateur est utilisé par un débogueur pour implémenter le suivi en une seule étape. Il ne doit pas être utilisé par d’autres applications. | ||
iopl | Niveau de privilège d’E/S | Niveau de privilège d’E/S Il s’agit d’un entier deux bits, avec des valeurs comprises entre zéro et 3. Il est utilisé par le système d’exploitation pour contrôler l’accès au matériel. Il ne doit pas être utilisé par les applications. |
Lorsque des registres sont affichés à la suite d’une commande dans la fenêtre Commande du débogueur, il s’agit de l’indicateur status qui s’affiche. Toutefois, si vous souhaitez modifier un indicateur à l’aide de la commande r (Registres), vous devez y faire référence par le code de l’indicateur.
Dans la fenêtre Registres de WinDbg, le code de l’indicateur est utilisé pour afficher ou modifier les indicateurs. L’indicateur status n’est pas pris en charge.
Voici un exemple. Dans l’affichage du registre précédent, l’indicateur status ng s’affiche. Cela signifie que l’indicateur de signe est actuellement défini sur 1. Pour modifier ce paramètre, utilisez la commande suivante :
r sf=0
Cela définit l’indicateur de signe sur zéro. Si vous effectuez un autre affichage de registre, le code ng status n’apparaît pas. Au lieu de cela, le code pl status s’affiche.
L’indicateur de signe, l’indicateur zéro et l’indicateur de transport sont les indicateurs les plus couramment utilisés.
Conditions
Une condition décrit l’état d’un ou de plusieurs indicateurs. Toutes les opérations conditionnelles sur le x86 sont exprimées en termes de conditions.
L’assembleur utilise une abréviation d’une ou deux lettres pour représenter une condition. Une condition peut être représentée par plusieurs abréviations. Par exemple, AE (« supérieur ou égal ») est la même condition que NB (« pas en dessous »). Le tableau suivant répertorie certaines conditions courantes et leur signification.
Nom de la condition | Indicateurs | Signification |
---|---|---|
Z |
ZF=1 |
Le résultat de la dernière opération était égal à zéro. |
NZ |
ZF=0 |
Le résultat de la dernière opération n’était pas égal à zéro. |
C |
CF=1 |
La dernière opération a nécessité un transport ou un emprunt. (Pour les entiers non signés, cela indique un dépassement de capacité.) |
NC |
CF=0 |
La dernière opération ne nécessitait pas de transport ou d’emprunt. (Pour les entiers non signés, cela indique un dépassement de capacité.) |
S |
SF=1 |
Le résultat de la dernière opération a son bit élevé défini. |
NS |
SF=0 |
Le résultat de la dernière opération a son bit élevé clair. |
O |
OF=1 |
Lorsqu’elle est traitée comme une opération d’entier signé, la dernière opération a provoqué un dépassement de capacité ou un flux inférieur. |
Non |
OF=0 |
Lorsqu’elle est traitée comme une opération d’entier signé, la dernière opération n’a pas causé de dépassement de capacité ou de sous-flux. |
Les conditions peuvent également être utilisées pour comparer deux valeurs. L’instruction cmp compare ses deux opérandes, puis définit les indicateurs comme s’ils sont soustraits un opérande de l’autre. Les conditions suivantes peuvent être utilisées pour case activée le résultat de cmpvalue1, value2.
Nom de la condition | Indicateurs | Signification après une opération CMP. |
---|---|---|
E |
ZF=1 |
value1 == value2. |
NE |
ZF=0 |
value1 != value2. |
GE NL | SF=OF |
value1>= value2. Les valeurs sont traitées comme des entiers signés. |
LE NG | ZF=1 ou SF !=OF |
value1<= value2. Les valeurs sont traitées comme des entiers signés. |
G NLE | ZF=0 et SF=OF |
value1>value2. Les valeurs sont traitées comme des entiers signés. |
L NGE | SF !=OF |
value1<value2. Les valeurs sont traitées comme des entiers signés. |
AE NB | CF=0 |
value1>= value2. Les valeurs sont traitées comme des entiers non signés. |
BE NA | CF=1 ou ZF=1 |
value1<= value2. Les valeurs sont traitées comme des entiers non signés. |
Un NBE | CF=0 et ZF=0 |
value1>value2. Les valeurs sont traitées comme des entiers non signés. |
B NAE | CF=1 |
value1<value2. Les valeurs sont traitées comme des entiers non signés. |
Les conditions sont généralement utilisées pour agir sur le résultat d’une instruction cmp ou de test . Par exemple,
cmp eax, 5
jz equal
compare le registre eax au nombre 5 en calculant l’expression (eax - 5) et en définissant des indicateurs en fonction du résultat. Si le résultat de la soustraction est égal à zéro, l’indicateur zr est défini et la condition jz est vraie afin que le saut soit effectué.
Types de données
octet : 8 bits
word : 16 bits
dword : 32 bits
qword : 64 bits (inclut des doubles à virgule flottante)
tword : 80 bits (inclut des doubles étendus à virgule flottante)
oword : 128 bits
Notation
Le tableau suivant indique la notation utilisée pour décrire les instructions du langage d’assembly.
Notation | Signification |
---|---|
r, r1, r2... |
Registres |
m |
Adresse mémoire (consultez la section Modes d’adressage suivants pour plus d’informations.) |
#n |
Constante immédiate |
r/m |
Inscrire ou mémoire |
r/#n |
Constante d’inscription ou immédiate |
r/m/#n |
Registre, mémoire ou constante immédiate |
Cc |
Code de condition répertorié dans la section Conditions précédente. |
T |
« B », « W » ou « D » (octet, mot ou dword) |
accT |
Accumulateur de taille T : al si T = « B », ax si T = « W », ou eax si T = « D » |
Modes d’adressage
Il existe plusieurs modes d’adressage différents, mais ils prennent tous la forme T ptr [expr], où T est un type de données (voir la section Types de données précédente) et expr une expression impliquant des constantes et des registres.
La notation de la plupart des modes peut être déduite sans grande difficulté. Par exemple, BYTE PTR [esi+edx*8+3] signifie « prendre la valeur du registre esi , y ajouter huit fois la valeur du registre edx , ajouter trois, puis accéder à l’octet à l’adresse résultante ».
Pipelining
Le Pentium est à double émission, ce qui signifie qu’il peut effectuer jusqu’à deux actions en une seule horloge. Toutefois, les règles sur le moment où il est capable d’effectuer deux actions à la fois ( appelées appairage) sont très compliquées.
Étant donné que x86 est un processeur CISC, vous n’avez pas à vous soucier des emplacements de délai de saut.
Accès à la mémoire synchronisé
Les instructions de chargement, de modification et de stockage peuvent recevoir un préfixe de verrou , qui modifie l’instruction comme suit :
Avant d’émettre l’instruction, le processeur vide toutes les opérations de mémoire en attente pour garantir la cohérence. Toutes les préversions de données sont abandonnées.
Lors de l’émission de l’instruction, le processeur dispose d’un accès exclusif au bus. Cela garantit l’atomicité de l’opération de chargement/modification/stockage.
L’instruction xchg obéit automatiquement aux règles précédentes chaque fois qu’elle échange une valeur avec la mémoire.
Toutes les autres instructions sont non verrouillées par défaut.
Prédiction de saut
Des sauts inconditionnels sont prévus.
Les sauts conditionnels sont prédits pour être effectués ou non, selon qu’ils ont été effectués la dernière fois qu’ils ont été exécutés. La taille du cache pour l’enregistrement de l’historique des sauts est limitée.
Si le processeur n’a pas d’enregistrement indiquant si le saut conditionnel a été effectué ou non lors de sa dernière exécution, il prédit les sauts conditionnels vers l’arrière comme étant effectués et les sauts conditionnels vers l’avant comme non effectués.
Alignement
Le processeur x86 corrige automatiquement l’accès à la mémoire non aligné, avec une pénalité de performances. Aucune exception n’est levée.
Un accès à la mémoire est considéré comme aligné si l’adresse est un multiple entier de la taille de l’objet. Par exemple, tous les accès BYTE sont alignés (tout est un multiple entier de 1), les accès WORD aux adresses paires sont alignés et les adresses DWORD doivent être un multiple de 4 pour être alignées.
Le préfixe de verrou ne doit pas être utilisé pour les accès à la mémoire non alignés.
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour