Section courante

A propos

Section administrative du site

Ensemble d'instructions pour les applications 80386

Cette page présente une vue d'ensemble des instructions que les programmeurs peuvent utiliser pour écrire un logiciel d'application pour le 80386 s'exécutant en mode d'adresse virtuelle protégée. Les instructions sont regroupées par catégories de fonctions associées.

Les instructions non abordées dans cette page sont celles n'étant normalement utilisées que par les programmeurs de systèmes d'exploitation.

Les descriptions de cette page supposent que le 80386 fonctionne en mode protégé avec un adressage 32 bits en vigueur ; cependant, toutes les instructions décrites sont également disponibles lorsque l'adressage 16 bits est en vigueur en mode protégé, en mode réel ou en mode virtuel 8086.

Instructions de déplacement de données

Ces instructions fournissent des méthodes pratiques pour déplacer des octets, des mots ou des mots doubles de données entre la mémoire et les registres de l'architecture de base. Ils appartiennent aux classes suivantes :

Instructions générales de déplacement des données

MOV (Move) transfère un octet, un mot ou un mot double de l'opérande source à l'opérande de destination. L'instruction MOV est utile pour transférer des données le long de l'un de ces chemins :

L'instruction MOV ne peut pas se déplacer de mémoire en mémoire ou de registre de segment en registre de segment n'est pas autorisée. Les déplacements de mémoire à mémoire peuvent cependant être effectués par l'instruction de déplacement de chaîne MOVS.

XCHG (Exchange) échange le contenu de deux opérandes. Cette instruction remplace les trois instructions MOV. Il ne nécessite pas d'emplacement temporaire pour enregistrer le contenu d'un opérande pendant que l'autre est en cours de chargement. XCHG est particulièrement utile pour implémenter des sémaphores ou des structures de données similaires pour la synchronisation des processus.

L'instruction XCHG peut échanger deux opérandes d'octet, deux opérandes de mot ou deux opérandes de mot double. Les opérandes de l'instruction XCHG peuvent être deux opérandes de registre ou un opérande de registre avec un opérande de mémoire. Lorsqu'il est utilisé avec un opérande mémoire, XCHG active automatiquement le signal LOCK.

Instructions de manipulation de pile

PUSH (Push) décrémente le pointeur de pile (ESP), puis transfère l'opérande source au sommet de la pile indiqué par ESP :

PUSH est souvent utilisé pour placer des paramètres sur la pile avant d'appeler une procédure ; c'est aussi le moyen de base de entreposer des variables temporaires sur la pile. L'instruction PUSH agit sur les opérandes de mémoire, les opérandes immédiats et les opérandes de registre (y compris les registres de segment).

PUSHA (Push All Registers) enregistre le contenu des huit registres généraux sur la pile :

Cette instruction simplifie les appels de procédure en réduisant le nombre d'instructions nécessaires pour conserver le contenu des registres généraux à utiliser dans une procédure.

Le microprocesseur pousse les registres généraux sur la pile dans l'ordre suivant : EAX, ECX, EDX, EBX, la valeur initiale de ESP avant que EAX ne soit poussé, EBP, ESI et EDI. PUSHA est complété par l'instruction POPA.

POP (Pop) transfère le mot ou le mot double au sommet actuel de la pile (indiqué par ESP) vers l'opérande de destination, puis incrémente ESP pour pointer vers le nouveau sommet de la pile :

POP déplace les informations de la pile vers un registre général ou vers la mémoire.

POPA (Pop All Registers) restaure les registres sauvegardés sur la pile par PUSHA, sauf qu'il ignore la valeur sauvegardée de ESP :

Instructions de conversion des types

Les instructions de conversion de type convertissent les octets en mots, les mots en mots doubles et les mots doubles en éléments 64 bits (mots quadruples). Ces instructions sont particulièrement utiles pour convertir des entiers signés, car elles remplissent automatiquement les bits supplémentaires de l'élément le plus grand avec la valeur du bit de signe de l'élément le plus petit. Ce type de conversion, illustré dans l'image suivante, est appelé extension de signe :

Il existe deux classes d'instructions de conversion de type :

  1. Les formats CWD, CDQ, CBW et CWDE fonctionnant uniquement sur les données du registre EAX.
  2. Les formats MOVSX et MOVZX, permettant à un opérande d'être dans n'importe quel registre général tout en permettant à l'autre opérande d'être en mémoire ou dans un registre.

CWD (Convert Word to Doubleword) et CDQ (Convert Doubleword to Quad-Word) doublent la taille de l'opérande source. CWD étend le signe du mot dans le registre AX dans tout le registre DX. CDQ étend le signe du mot double dans EAX à travers EDX. CWD peut être utilisé pour produire un dividende de mot double à partir d' un mot avant une division de mot, et CDQ peut être utilisé pour produire un dividende de quatre mots à partir d'un mot double avant la division de mot double.

CBW (Convert Byte to Word) étend le signe de l'octet dans le registre AL à travers AX.

CWDE (Convert Word to Doubleword Extended) étend le signe du mot dans le registre AX à travers EAX.

Le signe MOVSX (Move with Sign Extension) étend une valeur 8 bits à une valeur 16 bits et une valeur 8 ou 16 bits à une valeur 32 bits.

MOVZX (Move with Zero Extension) étend une valeur 8 bits à une valeur 16 bits et une valeur 8 ou 16 bits à une valeur 32 bits en insérant des zéros de poids fort.

Instructions arithmétiques binaires

Les instructions arithmétiques du microprocesseur 80386 simplifient la manipulation des données numériques codées en binaire. Les opérations incluent l'addition, la soustraction, la multiplication et la division standard ainsi que l'incrémentation, la décrémentation, la comparaison et le changement de signe. Les entiers binaires signés et non signés sont pris en charge. Les instructions arithmétiques binaires peuvent également être utilisées comme une étape dans le processus d'exécution de l'arithmétique sur des entiers décimaux.

De nombreuses instructions arithmétiques fonctionnent à la fois sur des entiers signés et non signés. Ces instructions mettent à jour les drapeaux ZF, CF, SF et OF de telle manière que les instructions suivantes peuvent interpréter les résultats de l'arithmétique comme signés ou non signés. CF contient des informations relatives aux entiers non signés ; SF et OF contiennent des informations relatives aux entiers signés. ZF concerne à la fois les entiers signés et non signés ; ZF est défini lorsque tous les bits du résultat sont à zéro.

Si l'entier n'est pas signé, CF peut être testé après l'une de ces opérations arithmétiques pour déterminer si l'opération nécessitait une retenue ou un emprunt d'un bit à la position d'ordre supérieur de l'opérande de destination. CF est défini si un bit a été exécuté à partir de la position d'ordre supérieur (instructions d'addition ADD, ADC, AAA et DAA) ou si un bit a été transporté (c'est-à-dire emprunté) dans le bit de poids fort (instructions de soustraction SUB, SBB, AAS, DAS, CMP et NEG).

Si l'entier est signé, SF et OF doivent être testés. SF a toujours la même valeur que le bit de signe du résultat. Le bit le plus significatif (MSB) d'un entier signé est le bit à côté du bit de signe 6 d'un octet, du bit 14 d'un mot ou du bit 30 d'un mot double. OF est défini dans l'un de ces cas :

Ces drapeaux d'état sont testés en exécutant l'une des deux familles d'instructions conditionnelles : Jcc (saut sur condition cc) ou SETcc (octet mis sur condition).

Instructions d'addition et de soustraction

ADD (Add Integers) remplace l'opérande de destination par la somme des opérandes source et destination. Définit CF en cas de débordement.

ADC (Add Integers with Carry) additionne les opérandes, en ajoute un si CF est défini et remplace l'opérande de destination par le résultat. Si CF est effacé, ADC effectue la même opération que l'instruction ADD. Un ADD suivi de plusieurs instructions ADC peut être utilisé pour ajouter des nombres de plus de 32 bits.

INC (incrément) ajoute un à l'opérande de destination. INC n'affecte pas CF. Utilisez ADD avec une valeur immédiate de 1 si un incrément que les mises à jour portent (CF est nécessaire).

SUB (Subtract Integers) soustrait l'opérande source de l'opérande de destination et remplace l'opérande de destination par le résultat. Si un emprunt est requis, le CF est défini. Les opérandes peuvent être des octets signés ou non signés, des mots ou des doubles mots.

SBB (Subtract Integers with Borrow) soustrait l'opérande source de l'opérande de destination, soustrait 1 si CF est défini et renvoie le résultat à l'opérande de destination. Si CF est effacé, SBB effectue la même opération que SUB. SUB suivi de plusieurs instructions SBB peut être utilisé pour soustraire des nombres de plus de 32 bits. Si CF est effacé, SBB effectue la même opération que SUB.

DEC (Decrement) soustrait 1 de l'opérande de destination. DEC ne met pas à jour CF. Utilisez SUB avec une valeur immédiate de 1 pour effectuer une décrémentation affectant la retenue.

Comparaison et instruction de changement de signe

CMP (Compare) soustrait l'opérande source de l'opérande destination. Il met à jour OF, SF, ZF, AF, PF et CF mais ne modifie pas les opérandes source et destination. Une instruction Jcc ou SETcc ultérieure peut tester les indicateurs appropriés.

Instructions de multiplication

Le 80386 a des instructions de multiplication séparées pour les opérandes non signés et signés. MUL fonctionne sur des nombres non signés, tandis que IMUL fonctionne sur des entiers signés ainsi que sur des nombres non signés.

MUL (Unsigned Integer Multiply) effectue une multiplication non signée de l'opérande source et de l'accumulateur. Si la source est un octet, le microprocesseur le multiplie par le contenu de AL et renvoie le résultat double longueur à AH et AL. Si l'opérande source est un mot, le microprocesseur le multiplie par le contenu de AX et renvoie le résultat de longueur double à DX et AX. Si l'opérande source est un mot double, le processeur le multiplie par le contenu de EAX et renvoie le résultat 64 bits dans EDX et EAX. MUL définit CF et OF lorsque la moitié supérieure du résultat est différente de zéro ; sinon, ils sont effacés.

IMUL (Signed Integer Multiply) effectue une opération de multiplication signée. IMUL a trois variantes :

  1. Un format à un opérande. L'opérande peut être un octet, un mot ou un mot double situé en mémoire ou dans un registre général. Cette instruction utilise EAX et EDX comme opérandes implicites de la même manière que l'instruction MUL.
  2. Un format à deux opérandes. L'un des opérandes source peut se trouver dans n'importe quel registre général tandis que l'autre peut se trouver soit en mémoire, soit dans un registre général. Le produit remplace l'opérande du registre général.
  3. Un format à trois opérandes ; deux sont la source et un est l'opérande de destination. L'un des opérandes source est une valeur immédiate entreposée dans l'instruction ; le second peut être en mémoire ou dans n'importe quel registre général. Le produit peut être entreposé dans n'importe quel registre général. L'opérande immédiat est traité comme signé. Si l'opérande immédiat est un octet, le microprocesseur l'étend automatiquement par signe à la taille du deuxième opérande avant d'effectuer la multiplication.

Les trois formats sont similaires à bien des égards :

Cependant, les formats 2 et 3 diffèrent en ce que le produit est tronqué à la longueur des opérandes avant d'être entreposé dans le registre de destination. En raison de cette troncature, OF doit être testé pour s'assurer qu'aucun bit significatif n'est perdu. (Pour savoir comment tester OF, reportez-vous aux instructions INTO et PUSHF.)

Les formats 2 et 3 d'IMUL peuvent également être utilisées avec des opérandes non signés car, que les opérandes soient signés ou non signés, la moitié de poids faible du produit est la même.

Instructions de division

Le 80386 a des instructions de division distinctes pour les opérandes non signés et signés. DIV fonctionne sur des nombres non signés, tandis que IDIV fonctionne sur des entiers signés ainsi que sur des nombres non signés. Dans les deux cas, une exception (interruption zéro) se produit si le diviseur est zéro ou si le quotient est trop grand pour AL, AX ou EAX.

DIV (Unsigned Integer Divide) effectue une division non signée de l'accumulateur par l'opérande source. Le dividende (l'accumulateur) est le double de la taille du diviseur (l'opérande source) ; le quotient et le reste ont la même taille que le diviseur, comme le montre le tableau suivant :

Taille de l'opérande source (diviseur) Dividende Quotient Reste
Octet AX AL AH
Mot DX:AX AX DX
Double mot EDX:EAX EAX EDX

Les quotients non entiers sont tronqués en nombres entiers vers 0. Le reste est toujours inférieur au diviseur. Pour la division d'octets non signés, le plus grand quotient est de 255. Pour la division de mots non signés, le plus grand quotient est de 65 535. Pour la division par mot double non signé, le plus grand quotient est 232-1.

IDIV (Signed Integer Divide) effectue une division signée de l'accumulateur par l'opérande source. IDIV utilise les mêmes registres que l'instruction DIV.

Pour la division d'octets signés, le quotient positif maximum est +127 et le quotient négatif minimum est -128. Pour la division de mots signés, le quotient positif maximum est de +32 767 et le quotient négatif minimum est de -32 768. Pour la division par double mot signé, le quotient positif maximum est 231-1, le quotient négatif minimum est -231. Les résultats non intégraux sont tronqués vers 0. Le reste a toujours le même signe que le dividende et est inférieur au diviseur en grandeur.

Instructions d'arithmétique décimale

L'arithmétique décimale est effectuée en combinant les instructions arithmétiques binaires (déjà discutées dans la section précédente) avec les instructions arithmétiques décimales. Les instructions d'arithmétique décimale sont utilisées de l'une des manières suivantes :

Ces instructions ne fonctionnent que sur les registres AL ou AH. La plupart utilisent les drapeaux AF.

Instructions de réglage du paquet BCD

DAA (Decimal Adjust after Addition) ajuste le résultat de l'ajout de deux opérandes décimaux compacts valides dans AL. DAA doit toujours suivre l'addition de deux paires de nombres décimaux compactés (un chiffre dans chaque demi-octet) pour obtenir une paire de chiffres décimaux compacts valides comme résultats. Le drapeau de portage est défini si le portage était nécessaire.

DAS (Decimal Adjust after Subtraction) ajuste le résultat de la soustraction de deux opérandes décimaux condensés valides dans AL. Le DAS doit toujours suivre la soustraction d'une paire de nombres décimaux condensés (un chiffre dans chaque demi-octet) d'une autre pour obtenir une paire de chiffres décimaux condensés valides comme résultat. L'indicateur de retenue est défini si un emprunt était nécessaire.

Instructions de réglage du BCD déballé

AAA (ASCII Adjust after Addition) modifie le contenu du registre AL en un nombre décimal non compressé valide et met à zéro les 4 premiers bits. AAA doit toujours suivre l'addition de deux opérandes décimaux non compressés dans AL. Le drapeau de retenue est défini et AH est incrémenté si une retenue est nécessaire.

AAS (ASCII Adjust after Subtraction) modifie le contenu du registre AL en un nombre décimal non compressé valide et met à zéro les 4 premiers bits. AAS doit toujours suivre la soustraction d'un opérande décimal décompressé d'un autre dans AL. Le drapeau de retenue est défini et AH décrémenté si un emprunt est nécessaire.

AAM (ASCII Adjust after Multiplication) corrige le résultat d'une multiplication de deux nombres décimaux non compressés valides. AAM doit toujours suivre la multiplication de deux nombres décimaux pour produire un résultat décimal valide. Le chiffre de poids fort est laissé dans AH, le chiffre de poids faible dans AL.

AAD (ASCII Adjust before Division) modifie le numérateur dans AH et AL pour préparer la division de deux opérandes décimaux non compressés valides afin que le quotient produit par la division soit un nombre décimal non compressé valide. AH doit contenir le chiffre de poids fort et AL le chiffre de poids faible. Cette instruction ajuste la valeur et place le résultat dans AL-AH contiendra zéro.

Instructions logiques

Le groupe d'instructions logiques comprend :

Instructions d'opération booléennes

Les opérations logiques sont AND, OR, XOR et NOT.

NOT (Pas) inverse les bits de l'opérande spécifié pour former un complément à un de l'opérande. L'instruction NOT est une opération unaire utilisant un seul opérande dans un registre ou une mémoire. NOT n'a aucun effet sur les drapeaux.

Les instructions AND, OR et XOR exécutent les opérations logiques standard "et", "(inclusif) ou" et "exclusif ou". Ces instructions peuvent utiliser les combinaisons d'opérandes suivantes :

AND, OR et XOR effacent OF et CF, laissent AF indéfini et mettent à jour SF, ZF et PF.

Instructions de test et de modification de bits

Ce groupe d'instructions opère sur un seul bit pouvant être en mémoire ou dans un registre général. L'emplacement du bit est spécifié sous la forme d'un déplacement par rapport à l'extrémité de poids faible de l'opérande. La valeur du déplacement peut soit être donnée par un octet immédiat dans l'instruction, soit être contenue dans un registre général.

Ces instructions affectent d'abord la valeur du "bit sélectionné à CF, le drapeau de retenue. Ensuite, une nouvelle valeur est affectée au bit sélectionné, comme déterminé par l'opération. OF, SF, ZF, AF, PF sont laissés dans un état indéfini. Le tableau suivant définit ces instructions :

Instruction Effet sur la CF Effet sur le bit sélectionné
BT (Test de bits) CF ← BIT (aucun)
BTS (Tester et définir les bits) CF ← BIT BIT ← 1
BTR (Test de bit et réinitialisation) CF ← BIT BIT ← 0
BTC (Test de bits et complément) CF ← BIT BIT ← NOT(BIT)

Instructions d'analyse de bits

Ces instructions analysent un mot ou un mot double à la recherche d'un bit et stockent l'index du premier bit défini dans un registre. La chaîne de bits analysée peut se trouver soit dans un registre, soit en mémoire. Le drapeau ZF est défini si le mot entier est égal à zéro (aucun bit défini n'est trouvé) ; ZF est effacé si un bit est trouvé. Si aucun bit défini n'est trouvé, la valeur du registre de destination est indéfinie.

BSF (Bit Scan Forward) balayage de l'ordre inférieur à l'ordre supérieur (en commençant par l'index de bit zéro).

BSR (Bit Scan Reverse) balayage de l'ordre supérieur à l'ordre inférieur (à partir de l'indice de bit 15 d'un mot ou de l'indice 31 d'un mot double).

Instructions de décalage et de rotation

Les instructions de décalage et de rotation repositionnent les bits dans l'opérande spécifié.

Ces instructions appartiennent aux classes suivantes :

Instructions de décalage

Les bits dans les octets, les mots et les mots doubles peuvent être décalés arithmétiquement ou logiquement. Selon la valeur d'un compte spécifié, les bits peuvent être décalés jusqu'à 31 positions.

Une instruction de décalage peut spécifier le comptage de trois manières. Une forme d'instruction de décalage spécifie implicitement le compte comme un décalage unique. La deuxième forme spécifie le nombre comme une valeur immédiate. La troisième forme spécifie le décompte comme la valeur contenue dans CL. Cette dernière forme permet au compte de décalage d'être une variable que le programme fournit pendant l'exécution. Seuls les 5 bits de poids faible de CL sont utilisés.

CF contient toujours la valeur du dernier bit décalé hors de l'opérande de destination. Dans un décalage d'un seul bit, OF est défini si la valeur du bit de poids fort (signe) a été modifiée par l'opération. Sinon, OF est effacé. Suite à un décalage multibit, cependant, le contenu de OF est toujours indéfini.

Les instructions de décalage fournissent un moyen pratique d'effectuer une division ou une multiplication par une puissance binaire. Notez cependant que la division des nombres signés par décalage vers la droite n'est pas le même type de division effectuée par l'instruction IDIV.

SAL (Shift Arithmetic Left) décale l'octet, le mot ou l'opérande de mot double de destination vers la gauche d'un ou du nombre de bits spécifié dans l'opérande de comptage (une valeur immédiate ou la valeur contenue dans CL). Le microprocesseur décale les zéros depuis le côté droit (de poids faible) de l'opérande lorsque les bits sortent du côté gauche (de poids fort).

SHL (Shift Logical Left) est synonyme de SAL.

SHR (Shift Logical Right) décale l'octet, le mot ou l'opérande de mot double de destination vers la droite d'un ou du nombre de bits spécifié dans l'opérande de comptage (une valeur immédiate ou la valeur contenue dans CL). Le microprocesseur décale les zéros du côté gauche de l'opérande lorsque les bits sortent du côté droit.

SAR (Shift Arithmetic Right) décale l'opérande d'octet, de mot ou de mot double de destination vers la droite d'un ou du nombre de bits spécifié dans l'opérande de comptage (une valeur immédiate ou la valeur contenue dans CL). Le processeur préserve le signe de l'opérande en décalant les zéros du côté gauche (de poids fort) si la valeur est positive ou en décalant de un si la valeur est négative.

Même si cette instruction peut être utilisée pour diviser des entiers par une puissance de deux, le type de division n'est pas le même que celui produit par l'instruction IDIV. Le quotient de IDIV est arrondi vers zéro, tandis que le "quotient" de SAR est arrondi vers l'infini négatif. Cette différence n'est apparente que pour les nombres négatifs. Par exemple, lorsque IDIV est utilisé pour diviser -9 par 4, le résultat est -2 avec un reste de -1. Si SAR est utilisé pour décaler -9 vers la droite de deux bits, le résultat est - 3. Le "reste" de ce type de division est + 3 ; cependant, l'instruction SAR n'entrepose que le bit de poids fort du reste (en CF).

La séquence de code suivant produit le même résultat que IDIV pour tout M = 2N, où 0 < N < 32. Cette séquence prend environ 12 à 18 horloges, selon que le saut est effectué ou non ; si ECX contient M, l'instruction IDIV ECX correspondante prendra environ 43 cycles d'horloge :

  1. ; en supposant que N est dans ECX et que le dividende est dans EAX
  2. ;                                                       CYCLES D'HORLOGE
  3. CMP EAX,0         ; mettre le drapeau de signe          2
  4. JGE NoAdjust      ; sauter si le signe est zéro         3 ou 9
  5. ADD EAX,ECX       ;                                     2
  6. DEC EAX           ; EAX := EAX + (N-1)                  2
  7. NoAdjust:
  8. SAR EAX,CL        ;                                     3
  9. ;                   CYCLE D'HORLOGE TOTAL              12 ou 18        

Instructions pour le double décalage

Ces instructions fournissent les opérations de base nécessaires pour mettre en ouvre des opérations sur de longues chaînes de bits non alignées. Les décalages doubles opèrent soit sur des opérandes mot soit sur mot double, comme suit :

  1. Prenant deux opérandes de mot en entrée et produisant une sortie d'un mot.
  2. Prenant deux opérandes de mot double en entrée et produisant une sortie de mot double.

Parmi les deux opérandes d'entrée, l'un peut être soit dans un registre général, soit en mémoire, tandis que l'autre ne peut être que dans un registre général. Les résultats remplacent la mémoire ou l'opérande de registre. Le nombre de bits à décaler est spécifié soit dans le registre CL, soit dans un octet immédiat de l'instruction.

Les bits sont décalés de l'opérande de registre vers la mémoire ou l'opérande de registre. CF est mis à la valeur du dernier bit décalé hors de l'opérande de destination. SF, ZF et PF sont définis en fonction de la valeur du résultat. OF et AF ne sont pas définis.

SHLD (Shift Left Double) décale les bits du champ R/M vers la gauche, tout en décalant les bits de poids fort du champ Reg vers le champ R/M sur la droite. Le résultat est entreposé dans l'opérande R/M. Le champ Reg n'est pas modifié.

SHRD (Shift Right Double) décale les bits du champ RIM vers la droite, tout en décalant les bits de poids faible du champ Reg vers le champ R/M sur la gauche. Le résultat est entreposé dans l'opérande R/M. Le champ Reg n'est pas modifié.

Rotation instructions

Les instructions de rotation permettent de faire pivoter des bits dans des octets, des mots et des mots doubles. Les bits pivotés hors d'un opérande ne sont pas perdus comme dans un décalage, mais sont «encerclés» dans l'autre «extrémité» de l'opérande.

Les rotations n'affectent que les drapeaux de report et de débordement. CF peut agir comme une extension de l'opérande dans deux des instructions de rotation, permettant d'isoler un bit puis de le tester par une instruction de saut conditionnel (JC ou JNC). CF contient toujours la valeur du dernier bit pivoté, même si l'instruction n'utilise pas ce bit comme extension de l'opérande pivoté.



Dernière mise à jour : Mercredi, le 26 juillet 2023