Intel x86 Assembly Language & Microarchitecture
Notions fondamentales sur les registres
Recherche…
Registres 16 bits
Lorsque Intel a défini le 8086 d'origine, il s'agissait d'un processeur 16 bits avec un bus d'adresse 20 bits (voir ci-dessous). Ils ont défini 8 registres 16 bits polyvalents - mais leur ont donné des rôles spécifiques pour certaines instructions:
-
AXLe registre des accumulateurs.
De nombreux opcodes ont pris ce registre ou ont été plus rapides s’ils ont été spécifiés. -
DXLe registre de données.
Cela était parfois combiné avec les 16 bits supérieurs d'une valeur de 32 bits avecAX- par exemple, comme résultat d'une multiplication. -
CXLe registre Count.
Cela a été utilisé dans un certain nombre d'instructions orientées boucle comme compteur implicite pour ces boucles - par exempleLOOPNE(boucle si elle n'est pas égale) etREP(mouvement répété / comparaison). -
BXLe registre de base.
Cela pourrait être utilisé pour indexer la base d'une structure en mémoire - aucun des registres ci-dessus ne pourrait être utilisé pour indexer directement dans la mémoire. -
SILe registre d'index source.
C'était l'index source implicite en mémoire pour certaines opérations de déplacement et de comparaison. -
DILe registre d'index de destination.
C'était l'index de destination implicite dans la mémoire pour certaines opérations de déplacement et de comparaison. -
SPLe registre Stack Pointer.
C'est le registre le moins polyvalent de l'ensemble! Il indiquait la position actuelle dans la pile, qui était utilisée explicitement pour les opérationsPUSHetPOP, implicitement pourCALLetRETavec des sous-routines, et TRÈS implicitement pendant les interruptions. En tant que tel, l'utiliser pour autre chose était dangereux pour votre programme! -
BPLe registre de pointeur de base.
Lorsque les sous-routines appellent d'autres sous-routines, la pile contient plusieurs "cadres de pile".BPpourrait être utilisé pour contenir le frame de pile actuel, puis lorsqu'un nouveau sous-programme était appelé, il devrait être sauvegardé sur la pile, le nouveau frame de pile créé et utilisé, et après retour du sous-programme interne .
Remarques:
Les trois premiers registres ne peuvent pas être utilisés pour l'indexation en mémoire.
BX,SIetDIpar défaut dans le segment de données actuel (voir ci-dessous).MOV AX, [BX+5] ; Point into Data Segment MOV AX, ES:[DI+5] ; Override into Extra SegmentDI, lorsqu'il est utilisé dans les opérations de mémoire à mémoire tels queMOVSetCMPS, utilise uniquement le segment supplémentaire (voir ci - dessous). Cela ne peut pas être remplacé.SPetBPutilisent le segment de pile (voir ci-dessous) par défaut.
Registres 32 bits
Lorsque Intel a produit le 80386, ils sont passés d'un processeur 16 bits à un processeur 32 bits. Le traitement 32 bits signifie deux choses: à la fois les données manipulées étaient 32 bits et les adresses mémoire auxquelles on accédait étaient 32 bits. Pour ce faire, tout en restant compatibles avec leurs processeurs antérieurs, ils ont introduit de nouveaux modes pour le processeur. C'était soit en mode 16 bits, soit en mode 32 bits - mais vous pouvez remplacer ce mode instruction par instruction pour les données, l'adressage ou les deux!
Tout d'abord, ils devaient définir des registres 32 bits. Pour ce faire, ils ont simplement étendu les huit bits existants de 16 à 32 bits et leur ont donné des noms "étendus" avec un préfixe E : EAX , EBX , ECX , EDX , ESI , EDI , EBP et ESP . Les 16 bits inférieurs de ces registres étaient les mêmes que précédemment, mais les moitiés supérieures des registres étaient disponibles pour les opérations 32 bits telles que ADD et CMP . Les moitiés supérieures n'étaient pas accessibles séparément comme elles l'avaient fait avec les registres à 8 bits.
Le processeur devait disposer de modes 16 et 32 bits distincts car Intel utilisait les mêmes codes d'opération pour la plupart des opérations: CMP AX,DX en mode 16 bits et CMP EAX,EDX en mode 32 bits avaient exactement les mêmes codes d'opération. ! Cela signifiait que le même code ne pouvait pas être exécuté dans les deux modes:
Le code opération de "Move immediate into
AX" est0xB8, suivi de deux octets de la valeur immédiate:0xB8 0x12 0x34
L'opcode pour "Move immediate into
EAX" est0xB8, suivi de quatre octets de la valeur immédiate:0xB8 0x12 0x34 0x56 0x78
Ainsi, l'assembly doit savoir dans quel mode se trouve le processeur lors de l'exécution du code, afin qu'il sache émettre le nombre d'octets correct.
Registres 8 bits
Les quatre premiers registres à 16 bits peuvent avoir leurs propres octets supérieurs et inférieurs accessibles directement en tant que leurs propres registres:
-
AHetALsont les moitiés haute et basse du registreAX. -
BHetBLsont les moitiés haute et basse du registreBX. -
CHetCLsont les moitiés haute et basse du registreCX. -
DHetDLsont les moitiés haute et basse du registreDX.
Notez que si vous modifiez AH ou AL , vous modifierez immédiatement AX ! Notez également que toute opération sur un registre à 8 bits ne pourrait pas affecter son "partenaire" - l'incrémentation de AL telle qu'elle déborde de 0xFF à 0x00 ne modifierait pas AH .
Les registres 64 bits ont également des versions 8 bits représentant leurs octets inférieurs:
-
SILpourRSI -
DILpourRDI -
BPLpourRBP -
SPLpourRSP
Il en va de même pour les registres R8 à R15 : leurs parties respectives d'octets inférieurs sont nommées R8B - R15B .
Registres de segments
Segmentation
Lorsque Intel concevait l'original 8086, il existait déjà un certain nombre de processeurs 8 bits dotés de capacités 16 bits, mais ils souhaitaient produire un véritable processeur 16 bits. Ils souhaitaient également produire quelque chose de meilleur et de plus performant que ce qui existait déjà. Ils souhaitaient donc pouvoir accéder à plus de 65 536 octets de mémoire maximum impliqués par les registres d'adressage 16 bits.
Registres de segments originaux
Ils ont donc implémenté l'idée de "Segments" - un bloc de mémoire de 64 kilo-octets indexé par les registres d'adresses à 16 bits - qui pourrait être recréé pour traiter différentes zones de la mémoire totale. Pour contenir ces bases de segment, ils comprenaient des registres de segments:
-
CSLe registre de segment de code.
Cela contient le segment du code en cours d'exécution, indexé par le registre impliciteIP(Instruction Pointer). -
DSLe registre de segment de données.
Cela contient le segment par défaut pour les données manipulées par le programme. -
ESLe registre Extra Segment.
Cela contient un deuxième segment de données, pour des opérations de données simultanées sur toute la mémoire. -
SSLe registre de segment de pile.
Cela contient le segment de mémoire qui contient la pile actuelle.
Taille du segment?
Les registres de segment peuvent avoir n'importe quelle taille, mais leur largeur de 16 bits facilite l'interopérabilité avec les autres registres. La question suivante était la suivante: les segments devraient-ils se chevaucher et, si oui, dans quelle mesure? La réponse à cette question dicterait la taille totale de la mémoire accessible.
S'il n'y avait pas de chevauchement du tout, l'espace d'adressage serait alors de 32 bits - 4 gigaoctets - une taille totalement inconnue à l'époque! Un chevauchement plus "naturel" de 8 bits produirait un espace d'adressage de 24 bits, soit 16 mégaoctets. En fin de compte, Intel a décidé de sauvegarder quatre autres adresses sur le processeur en rendant l’espace d’adresse de 1 mégaoctet avec un chevauchement de 12 bits.
Plus de registres de segments!
Lorsque Intel a conçu le 80386, ils ont reconnu que la suite existante de 4 registres de segments ne suffisait pas à la complexité des programmes qu’ils souhaitaient pouvoir prendre en charge. Ils ont donc ajouté deux autres:
-
FSLe registre du segment lointain -
GSLe registre du segment global
Ces nouveaux registres de segment n’avaient aucune utilisation imposée par le processeur: ils étaient simplement disponibles pour tout ce que le programmeur voulait.
Certains disent que les noms ont été choisis simplement pour continuer le thème
C,D,Ede l'ensemble existant ...
Registres 64 bits
AMD est un fabricant de processeurs qui avait autorisé la conception du 80386 d’Intel pour produire des versions compatibles, mais concurrentes. Ils ont apporté des modifications internes à la conception pour améliorer le débit ou d’autres améliorations apportées à la conception, tout en pouvant exécuter les mêmes programmes.
Pour un seul Intel, ils ont proposé des extensions 64 bits à la conception Intel 32 bits et ont produit la première puce 64 bits qui pouvait encore exécuter du code x86 32 bits. Intel a suivi la conception d'AMD dans ses versions de l'architecture 64 bits.
La conception 64 bits a apporté un certain nombre de modifications au jeu de registres, tout en restant compatible avec les versions antérieures:
- Les registres à usage général existants ont été étendus à 64 bits et nommés avec un préfixe
R:RAX,RBX,RCX,RDX,RSI,RDI,RBPetRSP.Encore une fois, les moitiés inférieures de ces registres étaient les mêmes que les registres de préfixe
E, et les moitiés supérieures ne pouvaient pas être consultées indépendamment. - 8 registres 64 bits supplémentaires ont été ajoutés et non nommés mais simplement numérotés:
R8,R9,R10,R11,R12,R13,R14etR15.- La moitié basse de 32 bits de ces registres est
R8DàR15D(D pour DWORD comme d'habitude). - Les 16 bits les plus bas de ces registres sont accessibles en ajoutant un
Wau nom du registre:R8WàR15W.
- La moitié basse de 32 bits de ces registres est
- Les 8 bits les plus bas des 16 registres sont désormais accessibles:
- Les traditionnels
AL,BL,CLetDL; - Les octets bas des registres de pointeurs (traditionnellement):
SIL,DIL,BPLetSPL; - Et les octets bas des 8 nouveaux registres:
R8BàR15B. - Cependant,
AH,BH,CHetDHsont inaccessibles dans les instructions qui utilisent un préfixe REX (pour une taille d'opérande de 64 bits, ou pour accéder à R8-R15, ou pour accéder àSIL,DIL,BPLouSPL). Avec un préfixe REX, le modèle de bit de code machine qui signifiaitAHau lieu de cela signifieSPL, et ainsi de suite. Voir le tableau 3-1 du manuel de référence des instructions d'Intel (volume 2).
- Les traditionnels
L'écriture dans un registre 32 bits met toujours à zéro les 32 bits supérieurs du registre pleine largeur, contrairement à l'écriture dans un registre 8 ou 16 bits (qui fusionne avec l'ancienne valeur, ce qui constitue une dépendance supplémentaire pour l'exécution hors ordre) ).
Registre des drapeaux
Lorsque l'unité ALU (Arithmetic Logic Unit) x86 effectue des opérations comme NOT et ADD , elle marque les résultats de ces opérations ("devenu zéro", "débordé", "devenu négatif") dans un registre FLAGS spécial de 16 bits. Les processeurs 32 bits l'ont mis à niveau à 32 bits et l'ont appelé EFLAGS , tandis que les processeurs 64 bits l'ont mis à 64 bits et l'ont appelé RFLAGS .
Codes de condition
Mais quel que soit le nom, le registre n'est pas directement accessible (sauf pour quelques instructions - voir ci-dessous). Au lieu de cela, les indicateurs individuels sont référencés dans certaines instructions, telles que le saut conditionnel ou le jeu conditionnel, appelés Jcc et SETcc où cc signifie «code de condition» et fait référence au tableau suivant:
| Code de condition | prénom | Définition |
|---|---|---|
E , Z | Égal, zéro | ZF == 1 |
NE , NZ | Pas égal, pas zéro | ZF == 0 |
O | Débordement | OF == 1 |
NO | Pas de débordement | OF == 0 |
S | Signé | SF == 1 |
NS | Pas signé | SF == 0 |
P | Parité | PF == 1 |
NP | Pas de parité | PF == 0 |
| -------------- | ---- | ---------- |
C , B , NAE | Porter, en dessous, pas au-dessus ou égal | CF == 1 |
NC , NB , AE | Pas de transport, pas au-dessous, au-dessus ou égal | CF == 0 |
A , NBE | Ci-dessus, non inférieur ou égal | CF == 0 et ZF == 0 |
NA , BE | Non supérieur, inférieur ou égal | CF == 1 ou ZF == 1 |
| --------------- | ---- | ---------- |
GE , NL | Plus grand ou égal, pas moins | SF == OF |
NGE , L | Pas plus grand ou égal, moins | SF ! = OF |
G , NLE | Plus grand, pas moins ou égal | ZF == 0 et SF == OF |
NG , LE | Pas plus grand, moins ou égal | ZF == 1 ou SF ! = OF |
En 16 bits, soustraire 1 de 0 est 65,535 ou -1 selon que l'arithmétique non signée ou signée est utilisée - mais la destination contient 0xFFFF deux cas. Ce n'est qu'en interprétant les codes de condition que la signification est claire. C'est encore plus révélateur si 1 est soustrait de 0x8000 : en arithmétique non signée, cela change simplement 32,768 en 32,767 ; tandis qu'en arithmétique signée, elle change de -32,768 en 32,767 - un débordement beaucoup plus remarquable!
Les codes de condition sont regroupés en trois blocs dans le tableau: sign-unselevant, unsigned et signed. La désignation à l'intérieur des deux derniers blocs utilise "Above" et "Below" pour les non signés et "Greater" ou "Less" pour les signés. Donc, JB serait "Jump if Below" (non signé), alors que JL serait "Jump if Less" (signé).
Accéder à FLAGS directement
Les codes de condition ci-dessus sont utiles pour interpréter des concepts prédéfinis, mais les bits de drapeau réels sont également disponibles directement avec les deux instructions suivantes:
-
LAHFChargeAHenregistre avec Flags -
SAHFStoreAHs'inscrire dans les drapeaux
Seuls certains drapeaux sont copiés avec ces instructions. L'ensemble du EFLAGS FLAGS / EFLAGS / RFLAGS peut être sauvegardé ou restauré sur la pile:
-
PUSHF/POPFPoussée / PopFLAGS16 bits sur / depuis la pile -
PUSHFD/POPFDPush / Pop 32-bitEFLAGSsur / depuis la pile -
PUSHFQ/POPFQPush / PopRFLAGS64 bits sur / depuis la pile
Notez que les interruptions enregistrent et restaurent automatiquement le registre [R/E]FLAGS actuel.
Autres drapeaux
Outre les indicateurs ALU décrits ci-dessus, le registre FLAGS définit d'autres indicateurs d'état du système:
-
IFle drapeau d'interruption.
Ceci est défini avec l'instructionSTIpour activer globalement les interruptions et effacé avec l'instructionCLIpour désactiver globalement les interruptions. -
DFLe drapeau de direction.
Les opérations de mémoire à mémoire , tels queCMPSetMOVS(à comparer et à se déplacer entre des emplacements de mémoire) incrémenter automatiquement ou décrémenter les registres d'index en tant que partie de l'instruction. Le drapeauDFcelui qui se produit: s'ils sont effacés avec l'instructionCLD, ils sont incrémentés; si elles sont définies avec l'instructionSTD, elles sont décrémentées. -
TFLe drapeau de piège. Ceci est un indicateur de débogage. Le paramétrer mettra le processeur en mode "pas à pas": après chaque instruction, il appellera le "gestionnaire d'interruption en une seule étape", qui doit être géré par un débogueur. Il n'y a pas d'instructions pour définir ou effacer cet indicateur: vous devez manipuler le bit lorsqu'il est en mémoire.
80286 Drapeaux
Pour prendre en charge les nouvelles fonctionnalités multitâches du 80286, Intel a ajouté des indicateurs supplémentaires au registre FLAGS :
-
IOPLLe niveau de privilège E / S.
Pour protéger le code multitâche, certaines tâches nécessitaient des privilèges pour accéder aux ports d'E / S, tandis que d'autres devaient y accéder. Intel a introduit une échelle de privilège à quatre niveaux,002 étant le plus privilégié et112 le moins. SiIOPLétait inférieur au niveau de privilège actuel, toute tentative d'accès aux ports d'E / S ou d'activation ou de désactivation des interruptions entraînerait une défaillance de protection générale. - Indicateur de tâche imbriquée
NT.
Cet indicateur a été défini si une tâcheCALLune autre tâche, ce qui a provoqué un changement de contexte. Le drapeau défini a indiqué au processeur de faire un changement de contexte lorsque leRETété exécuté.
80386 Drapeaux
Le '386 avait besoin de drapeaux supplémentaires pour prendre en charge des fonctionnalités supplémentaires conçues dans le processeur.
-
RFLe drapeau de reprise.
Le `386 a ajouté des registres de débogage, qui pouvaient appeler le débogueur sur divers accès matériels, comme la lecture, l’écriture ou l’exécution d’un certain emplacement de mémoire. Cependant, lorsque le gestionnaire de débogage retournait pour exécuter l'instruction, l'accès appelait immédiatement le gestionnaire de débogage! Ou du moins si ce n'était pas pour l'indicateur de reprise, qui est automatiquement défini lors de l'entrée dans le gestionnaire de débogage, et effacé automatiquement après chaque instruction. Si l'indicateur de reprise est défini, le gestionnaire de débogage n'est pas appelé. -
VMThe Virtual 8086 Flag.
Pour prendre en charge le code 16 bits plus ancien ainsi que le code 32 bits plus récent, le 80386 pouvait exécuter des tâches 16 bits en mode "Virtual 8086", à l'aide d'un exécutif Virtual 8086. L'indicateur deVMa indiqué que cette tâche était une tâche virtuelle 8086.
80486 Drapeaux
Au fur et à mesure que l'architecture Intel s'améliorait, elle devenait plus rapide grâce à une technologie telle que les caches et l'exécution super-scalaire. Cela devait optimiser l’accès au système en faisant des hypothèses. Pour contrôler ces hypothèses, plus de drapeaux étaient nécessaires:
- Drapeau de vérification d'alignement
ACL'architecture x86 peut toujours accéder à des valeurs de mémoire multi-octets sur n'importe quelle limite d'octets, contrairement à certaines architectures qui exigent qu'elles soient alignées (les valeurs de 4 octets doivent être sur 4 octets). Cependant, cela était moins efficace, car plusieurs accès mémoire étaient nécessaires pour accéder aux données non alignées. Si l'indicateurACétait défini, un accès non aligné déclencherait une exception plutôt que d'exécuter le code. De cette façon, le code pourrait être amélioré pendant le développement avecACset, mais désactivé pour le code de production.
Drapeaux Pentium
Le Pentium a ajouté plus de support pour la virtualisation, plus le support de l'instruction CPUID :
-
VIFL'indicateur d'interruption virtuelle.
Ceci est une copie virtuelle de cette TâcheIF- si cette tâche veut ou non désactiver les interruptions, sans affecter réellement mondial Interruptions. -
VIPLe drapeau en attente d'interruption virtuelle.
Cela indique qu'une interruption a été virtuellement bloquée parVIF, de sorte que lorsque la tâche effectue uneSTIune interruption virtuelle peut être déclenchée. -
IDLe drapeauCPUID-allowed.
Indique si cette tâche doit exécuter l'instructionCPUID. Un moniteur virtuel peut le refuser et "mentir" à la tâche demandeuse si elle exécute l'instruction.