Assembleur 80x86 | JMP |
---|---|
INTEL 8086+, x86-64 | Jump |
Syntaxe
JMP destination |
Paramètres
Nom | Description |
---|---|
destination | Ce paramètre permet d'indiquer l'emplacement ou doit être poursuivi l'exécution. |
Description
Cette instruction permet d'effectuer un branchement à un emplacement mémoire spécifié. Par conséquent, l'instruction JMP transfère le contrôle du programme à un point différent du flux d'instructions sans enregistrer les informations de retour. L'opérande de destination (cible) spécifie l'adresse de l'instruction à laquelle on veut sauter. Cet opérande peut être une valeur immédiate, un registre à usage général ou un emplacement de mémoire. Cette instruction peut être utilisée pour exécuter 4 types de sauts différents :
- Saut à proximité (Near jump) : Saut d'une instruction dans le segment de code actuel (le segment actuellement désigné par le registre CS), parfois appelé saut d'intrasegment.
- Saut court (Short jump) : Saut rapproché dans lequel la plage de saut est limitée à une valeur comprise entre -128 et +127 octets par rapport à la valeur EIP actuelle.
- Saut long (Far jump) : Saut vers une instruction située dans un segment différent du segment de code actuel, mais ayant le même niveau de privilège, parfois appelé saut intersegment.
- Commutateur de tâches (Task switch) : Saut vers une instruction située dans une tâche différente.
Remarques
- Un commutateur de tâches ne peut être exécuté qu'en mode protégé.
- Saut à proximité et saut court (Near jump et short jump) : Lors de l'exécution d'un saut à proximité, le microprocesseur saute à l'adresse (dans le segment de code actuel) spécifiée avec l'opérande cible (destination). L'opérande cible spécifie soit un déplacement absolu (c'est-à-dire un déplacement de la base du segment de code), soit un déplacement relatif (un déplacement signé par rapport à la valeur actuelle du pointeur d'instruction dans le registre EIP). Un saut proche d'un déplacement relatif de 8 bits (rel8) est appelé saut court. Le registre CS n'est pas modifié lors de sauts à proximité ou sauts courts. Un déplacement absolu est spécifié indirectement dans un registre général ou dans un emplacement mémoire (r/m16 ou r/m32). L'attribut de taille d'opérande détermine la taille de l'opérande cible (16 ou 32 bits). Les déplacements absolus sont chargés directement dans le registre EIP. Si l'attribut de taille d'opérande est de 16, les 2 octets supérieurs du registre EIP sont effacés, ce qui donne une taille maximale du pointeur d'instruction de 16 bits. Un déplacement relatif (rel8, rel16 ou rel32) est généralement spécifié en tant qu'étiquette dans le code d'assemblage, mais au niveau du code machine, il est codé comme une valeur immédiate signée de 8, 16 ou 32 bits. Cette valeur est ajoutée à la valeur dans le registre EIP. (Ici, le registre EIP contient l'adresse de l'instruction suivant l'instruction JMP). Lorsque vous utilisez des déplacements relatifs, l'opcode (pour les sauts courts par rapport aux sauts à proximité) et l'attribut de taille d'opérande (pour les sauts presque relatifs) déterminent la taille de l'opérande cible (8, 16 ou 32 bits).
- Les sauts long en mode d'adressage réel ou Virtuel-8086 : Lors de l'exécution d'un saut long en mode d'adresse réelle ou virtuelle-8086, le microprocesseur saute au segment de code et au déplacement spécifié avec l'opérande cible (destination). Ici, l'opérande cible spécifie une adresse absolue absolue directement avec un pointeur (ptr16:16 ou ptr16:32) ou indirectement avec un emplacement de mémoire (m16:16 ou m16:32). Avec la méthode du pointeur, le segment et l'adresse de la procédure appelée sont codés dans l'instruction, en utilisant une adresse longue de 4 octets (taille d'opérande de 16 bits) ou de 6 octets (opérande de 32 bits). Avec la méthode indirecte, l'opérande cible spécifie un emplacement mémoire contenant une adresse longue de 4 octets (taille d'opérande de 16 bits) ou de 6 octets (taille d'opérande de 32 bits). L'adresse longue est chargée directement dans les registres CS et EIP. Si l'attribut de la taille de l'opérande est 16, les 2 octets supérieurs du registre EIP sont effacés.
- Saut long en mode protégé : Lorsque le microprocesseur fonctionne en mode protégé, l'instruction JMP peut être utilisée pour effectuer les 3 types de sauts suivants : Un saut long vers un segment de code conforme ou non conforme, un saut long à travers une porte d'appel, un commutateur de tâches. L'instruction JMP ne peut pas être utilisée pour effectuer des sauts long de niveau inter-privilège. En mode protégé, le microprocesseur utilise toujours la partie du sélecteur de segment de l'adresse long pour accéder au descripteur correspondant dans le GDT ou le LDT. Le type de descripteur (segment de code, porte d'appel, porte de tâche ou TSS) et les droits d'accès déterminent le type de saut à effectuer. Si le descripteur sélectionné concerne un segment de code, un saut long vers un segment de code au même niveau de privilège est effectué. (Si le segment de code sélectionné se trouve à un niveau de privilège différent et que le segment de code est non conforme, une exception de protection générale est générée.) Un saut important au même niveau de privilège en mode protégé est très similaire à celui effectué en mode d'adressage réel ou du mode virtuel-8086. L'opérande cible spécifie une adresse longue absolue soit directement avec un pointeur (ptr16:16 ou ptr16:32), soit indirectement avec un emplacement mémoire (m16:16 ou m16:32). L'attribut de taille d'opérande détermine la taille du déplacement (16 ou 32 bits) dans l'adresse long. Le nouveau sélecteur de segment de code et son descripteur sont chargés dans le registre CS et le déplacement par rapport à l'instruction est chargé dans le registre EIP. Notez qu'une porte d'appel peut également être utilisée pour effectuer un appel long vers un segment de code au même niveau de privilège. L'utilisation de ce mécanisme fournit un niveau supplémentaire d'indirection et constitue la méthode recommandée pour effectuer des sauts entre des segments de code 16 bits et 32 ??bits. Lors de l'exécution d'un saut long à travers une porte d'appel, le sélecteur de segment spécifié par l'opérande cible identifie la porte d'appel. (La partie déplacement de l'opérande cible est ignorée.) Le microprocesseur passe ensuite au segment de code spécifié dans le descripteur de porte d'appel et commence à exécuter l'instruction au déplacement spécifié dans la porte d'appel. Aucun commutateur de pile ne se produit. Là encore, l'opérande cible peut spécifier l'adresse longue de la porte de l'appel soit directement avec un pointeur (ptr16:16 ou ptr16:32), soit indirectement avec un emplacement mémoire (m16:16 ou m16:32). L'exécution d'un commutateur de tâche avec l'instruction JMP est un peu similaire à l'exécution d'un saut via un portail d'appels. Ici, l'opérande cible spécifie le sélecteur de segment de la porte de tâche pour la tâche sur laquelle on bascule (et la partie de déplacement de l'opérande cible est ignorée). La porte des tâches pointe à son tour sur le TSS pour la tâche, contenant les sélecteurs de segment pour le code de la tâche et les segments de pile. Le TSS contient également la valeur EIP de la prochaine instruction à exécuter avant la suspension de la tâche. Cette valeur de pointeur d'instruction est chargée dans le registre EIP afin que la tâche puisse s'exécuter à nouveau lors de l'instruction suivante. L'instruction JMP peut également spécifier directement le sélecteur de segment du TSS, ceci éliminant l'indirection de la porte des tâches.
- Notez que lorsque vous exécutez une tâche de commutateur avec une instruction JMP, le drapeau de tâche imbriquée (NT) n'est pas défini dans le registre EFLAGS et le champ de lien de tâche précédent du nouveau TSS n'est pas chargé avec le sélecteur TSS de l'ancienne tâche. Un retour à la tâche précédente ne peut donc pas être effectué en exécutant l'instruction IRET. La commutation de tâches avec l'instruction JMP diffère à cet égard de l'instruction CALL définissant le drapeau NT et enregistre les informations de liaison de tâche précédentes, permettant ainsi de retourner à la tâche appelante avec une instruction IRET.
- Mode Long : En mode 64 bits, la taille de l'opération de l'instruction est fixée à 64 bits. Si un sélecteur pointe vers une porte, alors RIP est égal au déplacement de 64 bits effectué depuis la porte; sinon RIP est égal au déplacement nul du pointeur long référencé dans l'instruction.
- Ordre d'instructions : Les instructions suivant un saut long peuvent être extraites de la mémoire avant la fin de l'exécution des instructions précédentes, mais elles ne s'exécuteront pas (même de manière spéculative) tant que toutes les instructions antérieures au saut long ne seront pas terminées (les dernières instructions pourront être exécutées avant les données entreposées par les instructions précédentes soit devenu globalement visible). Certaines situations peuvent conduire à la prochaine instruction séquentielle après l'exécution spéculative d'un JMP. Si le logiciel doit empêcher cela (par exemple, afin d'empêcher un canal côté exécution spéculative), un code opération d'instruction INT3 ou LFENCE peut être placé après le JMP quasi-indirect afin de bloquer l'exécution spéculative.
Algorithme
MODULE JMP(destination) SI near jump ALORS SI saut relatif court ALORS tempEIP ← EIP + destination SINON tempEIP ← destination FIN SI SI tempEIP est en dehors des limites du code segment ALORS EXCEPTION #GP(0) FIN SI SI taille de l'opérande = 32 bits ALORS EIP ← tempEIP SINON EIP ← tempEIP ∩ 0000FFFFh FIN SI FIN SI SI saut long ET (PE = 0 OU (PE = 1 ET VM = 1)) ALORS * Adresse réel ou mode virtuel 8086 tempEIP ← destination(offset) SI tempEIP est en dehors des limites du code de segment ALORS EXCEPTION #GP(0) FIN SI CS ← destination(Sélecteur de segment) SI taille de l'opérande = 32 bits ALORS EIP ← tempEIP SINON EIP ← tempEIP ∩ 0000FFFFh FIN SI FIN SI SI far jump ET (PE = 1 ET VM = 0) ALORS * Mode protégé, pas mode virtuel 8086 SI l'adresse effective dans les segments CS, DS, ES, FS, GS ou SS est illégale OU sélecteur de segment dans une destination d'opérande nulle ALORS EXCEPTION #GP(0) FIN SI SI index de sélecteur de segment n'est pas dans la limite de descripteur de table ALORS EXCEPTION #GP(nouveau sélecteur) FIN SI Lecture du type et de l'accès correct du descripteur de segment SI type de segment n'est pas conforme OU code de segment non conforme, appel le pont, tâche du pont, ou TSS ALORS EXCEPTION #GP(sélecteur de segment) FIN SI Type de dépendance et accès correct ALLER A CONFORMING-CODE-SEGMENT ALLER A NONCONFORMING-CODE-SEGMENT ALLER A CALL-GATE ALLER A TASK-GATE ALLER A TASK-STATE-SEGMENT SINON EXCEPTION #GP(Sélecteur de segment) FIN SI CONFORMING-CODE-SEGMENT: SI DPL > CPL ALORS EXCEPTION #GP(Sélecteur de segment) FIN SI SI segment pas présent ALORS EXCEPTION #NP(Sélecteur de segment) FIN SI tempEIP ← destination(Offset) SI Taille de l'opérande = 16 bits ALORS tempEIP ← tempEIP ∩ 0000FFFFh FIN SI SI tempEIP n'est pas dans la limite du code segment ALORS EXCEPTION #GP(0) FIN SI CS ← destination(Sélecteur de segment) CS(RPL) ← CPL EIP ← tempEIP FIN NONCONFORMING-CODE-SEGMENT: SI (RPL > CPL) OU (DPL = CPL) ALORS EXCEPTION #GP(Sélecteur de code segment) FIN SI SI segment n'est pas présent ALORS EXCEPTION #NP(Sélecteur de segment) FIN SI SI pointeur d'instruction est en dehors des limites du segment ALORS EXCEPTION #GP(0) FIN SI tempEIP ← destination(offset) SI taille de l'opérande = 16 bits ALORS tempEIP ← tempEIP ∩ 0000FFFFh FIN SI SI tempEIP n'est pas dans les limites du code segment ALORS EXCEPTION #GP(0) FIN SI CS ← destination(Sélecteur de segment) CS(RPL) ← CPL EIP ← tempEIP FIN CALL-GATE: SI appel de pont DPL < CPL OU appel de pont DPL < appel de pont de sélecteur de segment RPL ALORS EXCEPTION #GP(sélecteur d'appel de pont) FIN SI SI appel d'un pont non présent ALORS EXCEPTION #NP(Sélecteur d'appel de pont) FIN SI SI appel d'un pont du sélecteur de code segment est nulle ALORS EXCEPTION #GP(0) FIN SI SI appel d'un pont d'index de sélecteur de code de segment est en dehors des limites du descripteur de table ALORS EXCEPTION #GP(sélecteur de code segment) FIN SI Lecture du descripteur de code segment SI descripteur de code segment n'est pas indiquer dans le code segment OU descripteur de code segment est conforme et DPL > CPL OU decripteur de segment de code n'est pas conforme ET DPL = CPL ALORS EXCEPTION #GP(Sélecteur de code segment) FIN SI SI code segment n'est pas présent ALORS EXCEPTION #NP(sélecteur de code segment) FIN SI SI pointeur d'instruction n'est pas dans les limites du code segment ALORS EXCEPTION #GP(0) FIN SI tempEIP ← destination(offset) SI Taille du pont = 16 bits ALORS tempEIP ← tempEIP ∩ 0000FFFFh FIN SI SI tempEIP n'est pas dans les limites du code segment ALORS EXCEPTION #GP(0) FIN SI CS ← destination(Sélecteur de segment) CS(RPL) ← CPL EIP ← tempEIP FIN TASK-GATE: SI tâche du pont DPL < CPL OU tâche du pont DPL < sélecteur de segment du pont de tâche RPL ALORS EXCEPTION #GP(Sélecteur de tâche du pont) FIN SI SI pont de tâche n'est pas présent ALORS EXCEPTION #NP(Sélecteur de pont) FIN SI Lecteur du sélecteur de segment TSS dans le descripteur de pont de tâche SI bit de sélecteur de segment TSS local/global est fixer à local OU index n'est dans les limites du GDT OU que le descripteur TSS specifié est occupé ALORS EXCEPTION #GP(Sélecteur TSS) FIN SI SI TSS n'est pas présent ALORS EXCEPTION #NP(Sélecteur TSS) FIN SI SWITCH-TASKS à TSS SI EIP n'est dans les limites de code de segment ALORS EXCEPTION #GP(0) FIN SI FIN TASK-STATE-SEGMENT: SI TSS DPL < CPL OU TSS DPL < sélecteur de segment TSS RPL OU descripteur TSS indique que le TSS n'est pas disponible ALORS EXCEPTION #GP(Sélecteur TSS) FIN SI SI TSS n'est pas présent ALORS EXCEPTION #NP(Sélecteur TSS) FIN SI SWITCH-TASKS à TSS SI EIP n'est pas dans les limites de code segment ALORS EXCEPTION #GP(0) FIN SI FIN |
Mnémonique
Instruction | Opcode | Description |
---|---|---|
JMP rel8off | EBh cb | Saut court à la destination spécifié par un déplacement signé de 8 bits |
JMP rel16off | E9h cw | Saut court à la destination spécifié par un déplacement signé de 16 bits |
JMP rel32off | E9h cd | Saut court à la destination spécifié par un déplacement signé de 32 bits |
JMP reg/mem16 | FFh /4 | Saut court à la destination spécifié par un le registre/mémoire 16 bits |
JMP reg/mem32 | FFh /4 | Saut court à la destination spécifié par un le registre/mémoire 32 bits |
JMP reg/mem64 | FFh /4 | Saut court à la destination spécifié par un le registre/mémoire 64 bits |
JMP FAR pntr16:16 | EAh cd | Saut long direct avec la destination spécifié par un long pointeur contenu dans l'instruction. Cette instruction est invalide en mode 64 bits. |
JMP FAR pntr16:32 | EAh cp | Saut long direct avec la destination spécifié par un long pointeur contenu dans l'instruction. Cette instruction est invalide en mode 64 bits. |
JMP FAR mem16:16 | FFh /5 | Saut long indirect avec la destination spécifié par un long pointeur contenu en mémoire. Cette instruction est invalide en mode 64 bits. |
JMP FAR mem16:32 | FFh /5 | Saut long indirect avec la destination spécifié par un long pointeur contenu en mémoire. Cette instruction est invalide en mode 64 bits. |
Exceptions
Message | Mode réel | Virtuel 8086 | Mode protégé | Description |
---|---|---|---|---|
#UD(Opcode invalide) | X | X | X | Cette instruction est exécuté en mode 64-bits avec un code un opcode indirect JMP (FFh /5) dans un opérande de registre. |
X | Cette instruction est exécuté en mode 64-bits avec un code un opcode direct JMP (EAh) | |||
#SS(Pile non-canonique) | X | X | X | Une adresse mémoire dépasse la limite du segment de pile ou n'est pas canonique |
#NP(Sélecteur) | X | L'accès au segment de code, au pont d'appel, un pont de tâche, ou a un TSS non présent. | ||
#GP(Protection général) | X | X | X | Une adresse mémoire dépasse la limite du segment de données ou n'est pas canonique |
X | L'opérande de destination n'est pas dans un segment non écrivable | |||
X | Un segment de données nulle est utilisé comme référence mémoire | |||
#GP(Sélecteur) | X | La destination de sélecteur de segment de code est un sélecteur nulle. | ||
X | Un code, un pont d'appel, une tâche de pont, ou un descripteur TSS dépasse la limite de descripteur de table. | |||
X | Un sélecteur de segment de bit TI est fixé, mais le sélecteur LDT est un sélecteur nulle. | |||
X | Le descripteur de segment spécifié par l'instruction n'est pas un segment de code, une tâche de pont, un pont d'appel, ou un TSS disponible dans le mode «legacy», ou n'est pas un segment de code 64 bits ou un appel 64 bits long d'un pont dans le mode «long». | |||
X | Le RPL d'un sélecteur de segment de code non-conforme spécifié par l'instruction est supérieur au CPL, ou le DPL n'est pas égale au CPL. | |||
X | Le DPL du descripteur de segment de code spécifié est conforme quand l'instruction est supérieur au CPL. | |||
X | Le DPL est un pont d'appel, une tâche de pont, un descripteur TSS spécifié quand l'instruction est inférieur au CPL ou au RPL. | |||
X | Le sélecteur de segment spécifié par le pont d'appel ou le pont de tâche est un sélecteur nulle. | |||
X | Le descripteur de segment spécifié par l'appel de pont n'est pas un segment de code en mode «legacy» ou segment de code 64 bits dans un mode «long». | |||
X | Le DPL du descripteur de segment spécifié par le pont d'appel est supérieur au CPL et dans un segment conforme. | |||
X | Le DPL du descripteur de segment spécifié par le pont d'appel n'est pas égale au CPL et il n'est pas dans un segment conforme. | |||
X | L'attribut étendue du pont d'appel 64 bits n'est pas à 0. | |||
X | Le descripteur TSS n'est pas un LDT. | |||
#PF(Faute de page) | X | X | Une faute de page résultat de l'exécution de l'instruction | |
#AC(Vérifie l'alignement) | X | X | Un désalignement de la référence mémoire est effectué quand une vérification d'alignement est activé |
Exemple
Cet exemple permet d'effectuer un saut à partir d'un tableau d'adresse :
- .MODEL small
- .STACK 100h
- .DATA
- .CODE
- CheckVideoCard PROC NEAR
- MOV AX,1A00h
- INT 10h
- CMP AL,1Ah
- JNE @@Default
- @@RePass:
- AND BX,000Fh
- SHL BX,1
- JMP Word Ptr CS:[Offset @PS2Jmp+BX]
- @PS2Jmp:
- DW Offset @@NoEGAExist ; 0h
- DW Offset @@Default ; 1h
- DW Offset @@Default ; 2h
- DW Offset @@Default ; 3h
- DW Offset @@EgaDefault ; 4h
- DW Offset @@EgaDefault ; 5h
- DW Offset @@PGA ; 6h
- DW Offset @@VGAPS2 ; 7h
- DW Offset @@VGAPS2 ; 8h
- DW Offset @@Default ; 9h
- DW Offset @@MCGADigitalColor ; Ah
- DW Offset @@MCGAAnalogMono ; Bh
- DW Offset @@MCGAPS2 ; Ch
- DW Offset @@Default ; Dh
- DW Offset @@Default ; Eh
- DW Offset @@Default ; Fh
- @@Default:
- ; ...
- JMP @@SetCardNExit
- @@NoPCJunior:
- ; ...
- JMP @@SetCardNExit
- @@EgaDefault:
- ; ...
- JMP @@SetCardNExit
- @@PGA:
- ; ...
- JMP @@SetCardNExit
- @@VGAPS2:
- ; ...
- JMP @@SetCardNExit
- @@NoEGAExist:
- ; ...
- JMP @@SetCardNExit
- @@MCGADigitalColor:
- ; ...
- JMP @@SetCardNExit
- @@MCGAAnalogMono:
- ; ...
- JMP @@SetCardNExit
- @@MCGAPS2:
- ; ...
- @@SetCardNExit:
- RET
- ENDP
-
- .startup
- ; ...
- INT 21h
- MOV AX,4C00h
- INT 21h
- END
Voici un exemple, en Turbo Pascal 7, permettant d'afficher un message en utilisant le segment de code pour entreposer les données et sauter la partie du code étant en faite des données :
Voir également
Langage de programmation - Instruction assembleur 80x86 - Instruction Jump if (JA, JB, JC, JCX, JE,...)
Langage de programmation - Assembleur 8080 et 8085 - Référence des instructions 8080 et 8085 - JMP
Langage de programmation - SAS/JMP
Références
Le livre d'Or PC, Martin Althaus, 1992, ISBN: 2-7361-0934-1, page 816
AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions, Edition Advanced Micro Devices, Revision 3.14, September 2007, Publication No. 24594, page 135.
Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2A: Instruction Set Reference, A-M, Edition Intel, Mars 2010, Publication No. 253666-034US, page 619 à 629.