# Programmation Assembleur/x86/Les branchements

* Programmation Assembleur/x86
* Introduction
* Registres
* Les flags
* Copie entre registres et mémoire
* Les branchements
* La pile
* Les interruptions
* Opérations arithmétiques et logiques
* Interactions avec les périphériques
* Index
* Conclusion
* Modifier ce modèle
Par défaut, les instructions sont exécutées les unes à la suite des autres, en séquence. Les instructions de branchement ou de saut permettent de passer à une autre instruction que la suivante, pour diverses raisons :
* Effectuer une boucle, dans ce cas, le saut revient à une instruction antérieure,
* Sauter les instructions conditionnelles quand la condition est fausse,
* Appeler un sous-programme.

## Saut inconditionnel

Le saut réalisé par l'instruction JMP est effectué sans test de condition. Le seul paramètre de cette instruction est l'adresse où l'exécution doit se poursuivre. Cette adresse peut être une constante, ou contenue dans un emplacement mémoire (un pointeur).
Exemples :

## Saut conditionnel

Les instructions de saut conditionnel n'effectue le saut que si la condition correspondante est réalisée. Comme pour l'instruction JMP, le seul paramètre est une adresse. Toutefois, sur les anciens processeurs, l'adresse ne peut aller au delà de 128 octets en arrière ou 127 octets en avant, car l'adresse n'est codée que sur un octet signé. Dans ce cas, l'astuce est de sauter à une instruction JMP qui utilise une adresse codée sur plus d'octets.

### Comparaison puis saut(s)

En assembleur, les conditions if sont décomposées en deux instructions :
* Une opération de comparaison des opérandes réalisant une soustraction ne stockant pas le résultat mais effectue la mise à jour des indicateurs du registre FLAGS,
* Un saut conditionnel basé sur l'état des indicateurs du registre FLAGS.
Cette décomposition permet d'optimiser certains cas :
* Quand les mêmes opérandes sont comparés une seule comparaison est faite, suivie de plusieurs sauts conditionnels ;
* L'opération de comparaison peut être remplacée par une ou des instructions mettant à jour les indicateurs, ce qui peut éviter une comparaison après une opération arithmétique. Les appels aux fonctions systèmes retournent souvent un état erreur ou OK dans un indicateur du registre FLAGS pouvant être traité par un saut conditionnel dans l'application au retour de l'appel de la fonction.

### Sauts conditionnels

La table ci-dessous résume les instructions de saut conditionnel, une case contenant tous les alias de la même instruction :
| Instruction et synonymes | Signification (en anglais) | Condition nécessaire |
| JCXZ | Jump if CX is Zero | Registre CX (16 bits) égal à 0 |
| JECXZ | Jump if ECX is Zero | Registre CX (32 bits) égal à 0 |
| JRCXZ | Jump if RCX is Zero | Registre CX (64 bits) égal à 0 |
| JZ JE | Jump if Zero flag is set Jump if both operand were Equals | Indicateur Zéro à 1 ou quand les deux opérandes A et B sont égaux (A-B = 0) |
| JNZ JNE | Jump if No Zero flag is set Jump if both operand were Not Equals | Indicateur Zéro à 0 ou quand les deux opérandes A et B ne sont pas égaux (A-B != 0) |
| JS | Jump if Sign flag is set | Indicateur de signe à 1 (résultat négatif) |
| JNS | Jump if No Sign flag is set | Indicateur de signe à 0 (résultat positif) |
| JO | Jump if Overflow flag is set | Indicateur de débordement à 1 |
| JNO | Jump if No Overflow flag is set | Indicateur de débordement à 0 |
| JC JB JNAE | Jump if Carry flag is set Jump if Borrow flag is set / Jump if Below Jump if Not Above or Equal | Indicateur de retenue à 1 (A < B, c'est à dire A-B < 0, retenue) |
| JNC JNB JAE | Jump if No Carry flag is set Jump if No Borrow flag is set / Jump if Not Below Jump if Above or Equal | Indicateur de retenue à 0 (A >= B, c'est à dire A-B >= 0, pas de retenue) |
| JBE JNA | Jump if Jump if Below or Equal Jump if Not Above | Indicateur de retenue à 1 ou indicateur Zéro à 1 (A < B ou A = B, c'est à dire A-B <= 0) |
| JNBE JA | Jump if Jump if Not Below or Equal Jump if Above | Indicateur de retenue à 0 et indicateur Zéro à 0 (A >= B et A != B, c'est à dire A > B, A-B > 0) |
| JL JNGE | Jump if Lower Jump if Not Greater or Equal | Indicateur de débordement différent de l'indicateur de signe (A < B) |
| JNL JGE | Jump if Not Lower Jump if Greater or Equal | Indicateur de débordement et indicateur de signe égaux (A >= B) |
| JLE JNG | Jump if Lower or Equal Jump if Not Greater | Indicateur de débordement différent de l'indicateur de signe ou indicateur zéro à 1 (A <= B) |
| JNLE JG | Jump if Not Lower or Equal Jump if Greater | Indicateur de débordement et indicateur de signe égaux et indicateur zéro à 0 (A > B) |
| JP JPE | Jump if Parity flag is set Jump if Parity Even | Indicateur de parité à 1 (les 8 bits de poids faible du résultat de A-B comportent un nombre pair de bits à 1) |
| JNP JPO | Jump if No Parity flag is set Jump if Parity Odd | Indicateur de parité à 0 (les 8 bits de poids faible du résultat de A-B comportent un nombre impair de bits à 1) |
Les deux dernières instructions de saut conditionnel JPE et JPO permettent de déterminer un bit de parité pour un octet. Elles sont notamment utilisées lors de la communication par port série.

### Sauts conditionnels pour comparaison numérique

Les sauts conditionnels utilisables après la comparaison de deux nombres entiers varient selon que les nombres sont signés ou non-signés. L'interprétation diffère quand le bit de poids fort des deux nombres diffèrent.
Exemple de deux interprétations pour des mots de 16 bits :
| Valeur (hex) | Interprétation en entiers non-signés | Interprétation en entiers signés |
| AX = 8800 | 34816 | -30720 |
| BX = 45A0 | 17824 | +17824 |
| Comparaison | AX > BX | AX < BX |
Le tableau suivant montre les sauts conditionnels à utiliser selon l'interprétation des nombres comparés en non-signés ou signés.
| Comparaison | Entiers non signés | Entiers signés |
| $<$ | JB | JL |
| $>$ | JA | JG |
| $\leq$ | JBE | JLE |
| $\geq$ | JAE | JGE |
| $=$ | JE | JE |
| $\neq$ | JNE | JNE |

### Appel à un sous-programme

L'instruction CALL permet d'appeler un sous-programme. Le seul paramètre de cette instruction est l'adresse du sous-programme à appeler. Cette adresse peut être une constante, ou contenue dans un emplacement mémoire (un pointeur).
Exemples :
L'instruction CALL est similaire à JMP excepté qu'avant d'effectuer le saut à l'adresse indiquée, l'adresse de retour est enregistrée dans la pile :
* Pour un appel d'adresse proche, seul l'offset est sauvegardé.
* Pour un appel d'adresse lointaine, le segment et l'offset sont sauvegardés.
L'adresse de retour sauvegardée dans la pile est celle du premier octet de l'instruction qui suit l'instruction CALL. Le sous-programme doit se terminer par une instruction de retour pour restituer l'adresse sauvegardée dans les registres CS:IP :
* L'instruction RET (Return) restitue l'offset (sous-programme appelé avec adresse proche) ;
* L'instruction RETF (Return Far) restitue l'offset et le segment (sous-programme appelé avec adresse lointaine).
Il existe aussi une instruction IRET (Interruption Return) qui en plus restitue les indicateurs mais elle est utilisée plutôt en fin de routine de traitement des interruptions.