Intel x86 Assembly Language & Microarchitecture
Flux de contrôle
Recherche…
Sauts inconditionnels
jmp a_label ;Jump to a_label
jmp bx ;Jump to address in BX
jmp WORD [aPointer] ;Jump to address in aPointer
jmp 7c0h:0000h ;Jump to segment 7c0h and offset 0000h
jmp FAR WORD [aFarPointer] ;Jump to segment:offset in aFarPointer
Relatif près des sauts
jmp a_label est:
- près
Il spécifie uniquement la partie offset de l' adresse logique de destination. Le segment est supposé êtreCS. - relatif
La sémantique de l' instruction est saut rel octets avant 1 de la prochaine adresse d'instruction ouIP = IP + rel.
L'instruction est codée sous la forme EB <rel8> ou EB <rel16/32> , l'assembleur prenant la forme la plus appropriée, préférant généralement une forme plus courte.
La jmp SHORT a_label par assembleur est possible, par exemple avec NASM jmp SHORT a_label , jmp WORD a_label et jmp DWORD a_label génèrent les trois formes possibles.
Sauts indirects absolus
jmp bx et jmp WORD [aPointer] sont:
- près
Ils spécifient uniquement la partie offset de l'adresse logique de destination. Le segment est supposé êtreCS. - indirect indirect
La sémantique des instructions est sautée à l’adresse dans reg ou mem ouIP = reg,IP = mem.
L'instruction est codée comme FF /4 , pour la mémoire indirecte, la taille de l'opérande est déterminée comme pour tout autre accès mémoire.
Sauts absolus
jmp 7c0h:0000h est:
loin
Il spécifie les deux parties de l'adresse logique : le segment et le décalage.absolute La sémantique de l'instruction passe directement au segment d' adresse : offset ou
CS = segment, IP = offset.
L'instruction est codée comme EA <imm32/48> fonction de la taille du code.
Il est possible de choisir entre les deux formes dans un assembleur, par exemple avec NASM jmp 7c0h: WORD 0000h et jmp 7c0h: DWORD 0000h génère la première et la seconde forme.
Sauts absolus indirects
jmp FAR WORD [aFarPointer] est:
far Indique les deux parties de l'adresse logique : le segment et le décalage.
Absolue indirecte La sémantique de l'instruction est sautée vers le segment: offset stocké dans mem 2 ou
CS = mem[23:16/32], IP = [15/31:0].
L'instruction est codée comme FF /5 , la taille de l'opérande peut être contrôleur avec les spécificateurs de taille.
Dans NASM, un peu non intuitif, ils sont jmp FAR WORD [aFarPointer] pour un opérande 16:16 et jmp FAR DWORD [aFarPointer] pour un opérande 16:32 .
Sauts manquants
presque absolu
Peut être émulé avec un saut presque indirect.mov bx, target ;BX = absolute address of target jmp bxloin relatif
Cela n'a aucun sens ou est trop étroit d'utilisation.
1 Deux complément permet de spécifier un décalage signé et donc de revenir en arrière.
2 Ce qui peut être un seg16: off16 ou un seg16: off32 , de tailles 16:16 et 16:32 .
Conditions de test
Pour utiliser un saut conditionnel, une condition doit être testée. Tester une condition ici ne concerne que l'acte de vérifier les drapeaux, le saut réel est décrit sous sauts conditionnels .
x86 teste les conditions en s'appuyant sur le registre EFLAGS, qui contient un ensemble d'indicateurs que chaque instruction peut potentiellement définir.
Les instructions arithmétiques, comme sub ou add , et les instructions logiques, comme xor ou and , "définissent évidemment les drapeaux". Cela signifie que les drapeaux CF , OF , SF , ZF , AF , PF sont modifiés par ces instructions. Toute instruction est autorisée à modifier les indicateurs, par exemple cmpxchg modifie le ZF .
Toujours vérifier la référence de l'instruction pour savoir quels drapeaux sont modifiés par une instruction spécifique.
x86 possède un ensemble de sauts conditionnels , mentionnés précédemment, qui sautent si et seulement si certains indicateurs sont définis ou si certains sont clairs ou les deux.
Les drapeaux
Les opérations arithmétiques et logiques sont très utiles pour définir les indicateurs. Par exemple, après un sub eax, ebx , pour maintenant détenir des valeurs non signées , nous avons:
| Drapeau | Quand réglé | Lorsque clair |
|---|---|---|
| ZF | Lorsque le résultat est zéro. EAX - EBX = 0 ⇒ EAX = EBX | Lorsque le résultat n'est pas nul. EAX - EBX ≠ 0 ⇒ EAX ≠ EBX |
| CF | Quand le résultat a dû être porté pour le MSb. EAX - EBX <0 ⇒ EAX <EBX | Lorsque le résultat n'a pas besoin d'être porté pour le MSb. EAX - EBX ≮ 0 ⇒ EAX ≮ EBX |
| SF | Lorsque le résultat MSb est défini. | Lorsque le résultat MSb n'est pas défini. |
| DE | Quand un débordement signé s'est produit. | Lorsqu'un dépassement signé n'a pas eu lieu. |
| PF | Lorsque le nombre de bits défini dans l'octet de résultat le moins significatif est pair. | Lorsque le nombre de bits défini dans l'octet de résultat le moins significatif est impair. |
| UN F | Lorsque le chiffre inférieur BCD a généré un report. C'est le bit 4 transport. | Lorsque le chiffre inférieur BCD n'a pas généré de report. C'est le bit 4 transport. |
Tests non destructifs
Le sub -programme and instructions modifient leur opérande de destination et nécessitent deux copies supplémentaires (sauvegarde et restauration) pour que la destination ne soit pas modifiée.
Pour effectuer un test non destructif, il y a les instructions cmp et test . Ils sont identiques à leur homologue destructeur, sauf que le résultat de l'opération est ignoré et que seuls les indicateurs sont enregistrés .
| Destructeur | Non destructif |
|---|---|
sub | cmp |
and | test |
test eax, eax ;and eax, eax
;ZF = 1 iff EAX is zero
test eax, 03h ;and eax, 03h
;ZF = 1 if both bit[1:0] are clear
;ZF = 0 if at least one of bit[1:0] is set
cmp eax, 241d ;sub eax, 241d
;ZF = 1 iff EAX is 241
;CF = 1 iff EAX < 241
Tests signés et non signés
Le processeur ne donne aucune signification particulière pour enregistrer les valeurs 1 , le signe est une construction de programmeur. Il n'y a pas de différence lors du test des valeurs signées et non signées. Le processeur calcule suffisamment de drapeaux pour tester les relations arithmétiques habituelles (égales, inférieures à, supérieures à, etc.) si les opérandes devaient être considérées comme signées et non signées.
1 Bien que certaines instructions ne soient utiles que pour des formats spécifiques, comme le complément à deux. Cela permet de rendre le code plus efficace car l'implémentation de l'algorithme dans le logiciel nécessiterait beaucoup de code.
Sauts conditionnels
En fonction de l'état des indicateurs, le processeur peut soit exécuter soit ignorer un saut. Une instruction qui effectue un saut basé sur les indicateurs tombe sous le nom générique de Jcc - Jump on Condition Code 1 .
Synonymes et terminologie
Afin d'améliorer la lisibilité du code d'assemblage, Intel a défini plusieurs synonymes pour le même code de condition. Par exemple, jae , jnb et jnc ont tous le même code de condition CF = 0 .
Bien que le nom de l'instruction puisse donner une idée très précise de son utilisation, la seule approche utile consiste à reconnaître les indicateurs à tester, puis à choisir les instructions appropriées.
Intel a cependant donné les noms d'instructions qui ont un sens parfait lorsqu'elles sont utilisées après une instruction cmp . Pour les besoins de cette discussion, cmp sera supposé avoir défini les drapeaux avant un saut conditionnel.
Égalité
L'opérande est égal si ZF a été défini, ils diffèrent autrement. Pour tester l'égalité, nous avons besoin de ZF = 1 .
je a_label ;Jump if operands are equal
jz a_label ;Jump if zero (Synonym)
jne a_label ;Jump if operands are NOT equal
jnz a_label ;Jump if not zero (Synonym)
| Instruction | Les drapeaux |
|---|---|
je , jz | ZF = 1 |
jne , jnz | ZF = 0 |
Plus grand que
Pour les opérandes non signés , la destination est supérieure à la source si le transport n'est pas nécessaire, c'est-à-dire si CF = 0 . Lorsque CF = 0 il est possible que les opérandes soient égaux, le test de ZF va désambiguïser.
jae a_label ;Jump if above or equal (>=)
jnc a_label ;Jump if not carry (Synonym)
jnb a_label ;Jump if not below (Synonym)
ja a_label ;Jump if above (>)
jnbe a_label ;Jump if not below and not equal (Synonym)
| Instruction | Les drapeaux |
|---|---|
jae , jnc , jnb | CF = 0 |
ja , jnbe | CF = 0, ZF = 0 |
Pour les opérandes signés, nous devons vérifier que SF = 0 , sauf en cas de dépassement signé, auquel cas le SF résultant est inversé. Puisque OF = 0 si aucun débordement signé ne s'est produit et 1 sinon, nous devons vérifier que SF = OF .
ZF peut être utilisé pour implémenter un test strict / non strict.
jge a_label ;Jump if greater or equal (>=)
jnl a_label ;Jump if not less (Synonym)
jg a_label ;Jump if greater (>)
jnle a_label ;Jump if not less and not equal (Synonym)
| Instruction | Les drapeaux |
|---|---|
jge , jnl | SF = OF |
jg , jnle | SF = OF, ZF = 0 |
Moins que
Ceux-ci utilisent les conditions inversées ci-dessus.
jbe a_label ;Jump if below or equal (<=)
jna a_label ;Jump if not above (Synonym)
jb a_label ;Jump if below (<)
jc a_label ;Jump if carry (Synonym)
jnae a_label ;Jump if not above and not equal (Synonym)
;SIGNED
jle a_label ;Jump if less or equal (<=)
jng a_label ;Jump if not greater (Synonym)
jl a_label ;Jump if less (<)
jnge a_label ;Jump if not greater and not equal (Synonym)
| Instruction | Les drapeaux |
|---|---|
jbe , jna | CF = 1 ou ZF = 1 |
jb , jc , jnae | CF = 1 |
jle , jng | SF! = OF ou ZF = 1 |
jl , jnge | SF! = De |
Drapeaux spécifiques
Chaque indicateur peut être testé individuellement avec j<flag_name> où flag_name ne contient pas le F final (par exemple, CF → C , PF → P ).
Les autres codes non couverts sont les suivants:
| Instruction | Drapeau |
|---|---|
js | SF = 1 |
jns | SF = 0 |
jo | OF = 1 |
jno | OF = 0 |
jp , jpe (e = pair) | PF = 1 |
jnp , jpo (o = impair) | PF = 0 |
Un saut conditionnel supplémentaire (extra)
Un saut conditionnel x86 spécial ne teste pas le drapeau. Au lieu de cela, il teste la valeur du registre cx ou ecx (sur la base du mode d'adresse actuel du processeur, soit 16 ou 32 bits), et le saut est exécuté lorsque le registre contient zéro.
Cette instruction a été conçue pour la validation du registre de compteur ( cx/ecx ) avant les instructions de type rep , ou avant les loop de loop .
jcxz a_label ; jump if cx (16b mode) or ecx (32b mode) is zero
jecxz a_label ; synonym of jcxz (recommended in source code for 32b target)
| Instruction | Registre (pas de drapeau) |
|---|---|
jcxz , jecxz | cx = 0 (mode 16b) |
jcxz , jecxz | ecx = 0 (mode 32b) |
1 Ou quelque chose comme ça.
Tester les relations arithmétiques
Entiers non signés
Plus grand que
cmp eax, ebx
ja a_label
Meilleur que ou égal
cmp eax, ebx
jae a_label
Moins que
cmp eax, ebx
jb a_label
Inférieur ou égal
cmp eax, ebx
jbe a_label
Égal
cmp eax, ebx
je a_label
Inégal
cmp eax, ebx
jne a_label
Entiers signés
Plus grand que
cmp eax, ebx
jg a_label
Meilleur que ou égal
cmp eax, ebx
jge a_label
Moins que
cmp eax, ebx
jl a_label
Inférieur ou égal
cmp eax, ebx
jle a_label
Égal
cmp eax, ebx
je a_label
Inégal
cmp eax, ebx
jne a_label
a_label
Dans les exemples ci-dessus, le a_label est la destination cible du processeur lorsque la condition testée est "true". Lorsque la condition testée est "false", le processeur continue sur l'instruction suivante après le saut conditionnel.
Des synonymes
Il existe des synonymes d'instructions qui peuvent être utilisés pour améliorer la lisibilité du code.
Par exemple ja et jnbe (Jump non inférieur ni égal) sont la même instruction.
Codes compagnons non signés signés
| Opération | Non signé | Signé |
|---|---|---|
| > | ja | jg |
| > = | jae | jge |
| < | jb | jl |
| <= | jbe | jle |
| = | je | je |
| ≠,! =, <> | jne | jne |