Langage assembleur - Instructions logiques
Les instructions logiques sont utilisées pour des opérations au niveau du bit en programmation assembleur, largement utilisées pour le masquage, l'extraction de bits, le positionnement de drapeaux et la multiplication/division efficace.
AND - AND bit à bit
ANDEffectue une opération AND bit à bit sur deux opérandes (le résultat est 1 uniquement lorsque les deux bits valent 1).
Exemple
; Exemple d'instruction AND
section .text
global _start
_start:
; AND bit à bit de base
mov eax, 0x0F0F ; 0000 1111 0000 1111
and eax, 0x00FF ; 0000 0000 1111 1111
; Résultat : eax = 0x000F ; 0000 0000 0000 1111
; Technique courante 1 : masquer les 4 bits de poids faible (conserver les 4 bits de poids faible)
mov eax, 0xAB ; 1010 1011
and eax, 0x0F ; 0000 1111
; eax = 0x0B ; 0000 1011
; Technique courante 2 : vérifier la parité (AND avec 1)
mov eax, 42 ; Pair
and eax, 1 ; eax = 0 (pair)
; La représentation binaire de 42 se termine par 0, 42 & 1 = 0
mov eax, 43 ; Impair
and eax, 1 ; eax = 1 (impair)
; La représentation binaire de 43 se termine par 1, 43 & 1 = 1
; Technique courante 3 : mettre à zéro un registre
xor eax, eax ; Équivalent à mov eax, 0, mais plus rapide et plus court
; AND positionne les drapeaux : CF=0, OF=0, ZF et SF dépendent du résultat
mov eax, 1
mov ebx, 0
int 0x80
OR - OU bit à bit
OREffectue une opération OU bit à bit sur deux opérandes (le résultat est 1 si au moins un bit est 1).
Exemple
; Fusionner les bits de drapeau
mov eax, 0x0F00 ; 0000 1111 0000 0000
or eax, 0x00FF ; 0000 0000 1111 1111
; eax = 0x0FFF ; 0000 1111 1111 1111
; Définir un bit spécifique (mettre le bit 3 à 1)
mov eax, 0 ; 0000 0000
or eax, 0x08 ; 0000 1000
; eax = 0x8 ; 0000 1000
; Conversion de casse : majuscules en minuscules
mov al, 'A' ; al = 0x41 (0100 0001)
or al, 0x20 ; 0x20 = 0010 0000
; al = 0x61 = 'a' ; 0110 0001
NOT - NOT bit a bit
NOTInverte ogni bit dell'operando (0 diventa 1, 1 diventa 0).
Exemple
mov eax, 0x0F0F0F0F ; 0000 1111 0000 1111 ...
not eax ; 1111 0000 1111 0000 ...
; eax = 0xF0F0F0F0
; NOT non influisce su alcun flag (a differenza di AND/OR/XOR)
XOR - XOR bit a bit
XOREsegue un'operazione XOR bit a bit su due operandi (il risultato è 1 se i bit differiscono, 0 se sono uguali).
Exemple
; esempio di istruzione XOR
section .text
global _start
_start:
; XOR di base
mov eax, 0x0F0F ; 0000 1111 0000 1111
xor eax, 0x00FF ; 0000 0000 1111 1111
; Résultat : eax = 0x0FF0 ; 0000 1111 1111 0000
; Technique classique 1 : mettre un registre à zéro (plus efficace que mov reg, 0)
xor eax, eax ; eax = 0, n'occupe que 2 octets
xor ebx, ebx
xor ecx, ecx
; Technique classique 2 : échanger deux registres (aucun troisième registre temporaire nécessaire)
mov eax, 100 ; eax = 100
mov ebx, 200 ; ebx = 200
xor eax, ebx ; eax = 100 xor 200
xor ebx, eax ; ebx = 200 xor (100 xor 200) = 100
xor eax, ebx ; eax = (100 xor 200) xor 100 = 200
; Maintenant eax = 200, ebx = 100 (échange terminé !)
; Technique classique 3 : chiffrement/déchiffrement simple
mov al, 'A' ; Caractère original 'A' = 0x41
xor al, 0x55 ; Chiffrement : al = 'A' xor 0x55
; al est maintenant une valeur brouillée
xor al, 0x55 ; Déchiffrement : XOR avec 0x55 à nouveau pour restaurer
; al = 'A' est de retour !
mov eax, 1
mov ebx, 0
int 0x80
L'astuce d'échange par XOR est sympa, mais sur les processeurs modernes, elle est moins efficace que d'utiliser
XCHGune instruction ou un registre temporaire. C'est bon à savoir, mais pas besoin d'insister pour l'utiliser.
Instructions de décalage
Les instructions de décalage déplacent les bits binaires vers la gauche ou la droite, couramment utilisées pour une multiplication et une division efficaces (multiplier par 2, diviser par 2, etc.).
| Instruction | Fonction | Exemple |
|---|---|---|
| SHL | Décalage logique à gauche (les bits sortent à gauche, des zéros remplissent à droite) | shl eax, 1(multiplier par 2) |
| SHR | Décalage logique à droite (les bits sortent à droite, des zéros sont insérés à gauche) | shr eax, 1(division non signée par 2) |
| SAL | Décalage arithmétique à gauche (identique à SHL) | sal eax, 1 |
| SAR | Décalage arithmétique à droite (les bits sortent à droite, le bit de signe est conservé à gauche) | sar eax, 1(division signée par 2) |
Exemple
; Exemple d'instruction de décalage
section .text
global _start
_start:
; SHL : décalage logique à gauche = multiplication par une puissance de 2
mov eax, 10 ; eax = 10 (1010)
shl eax, 1 ; eax = 20 (10100), soit 10×2
shl eax, 2 ; eax = 80 (1010000), soit 20×4
; SHR : décalage logique à droite = division non signée par une puissance de 2
mov eax, 80 ; eax = 80
shr eax, 3 ; eax = 10, soit 80÷8
; SAR : décalage arithmétique à droite = division signée par une puissance de 2 (préserve le bit de signe)
mov eax, -16 ; eax = -16 (0xFFFFFFF0)
sar eax, 2 ; eax = -4 (0xFFFFFFFC), soit -16÷4
; SAR vs SHR :
; Si eax = 0xFFFFFFF0 (-16), SHR donne 0x3FFFFFFC (un très grand nombre positif)
; alors que SAR donne 0xFFFFFFFC (-4), en préservant le bit de signe
; Le dernier bit décalé vers l'extérieur est placé dans le drapeau CF
mov eax, 5 ; 0101
shr eax, 1 ; eax = 2, CF = 1 (le 1 final a été décalé vers l'extérieur)
jc carry_was_set ; Si CF=1, le nombre d'origine était impair
carry_was_set:
mov eax, 1
mov ebx, 0
int 0x80
Instructions de rotation
Les décalages de rotation réinjectent le bit décalé à l'autre extrémité, formant une rotation :
| Instruction | Description |
|---|---|
| ROL | Rotation à gauche (contourne CF) |
| ROR | Rotation à droite (contourne CF) |
| RCL | Rotation à gauche via la retenue (implique CF) |
| RCR | Rotation à droite via la retenue (implique CF) |
Exemple
; ROL : rotation à gauche
mov al, 0x85 ; 1000 0101
rol al, 1 ; Décalage à gauche de 1 bit : 0000 1011
; CF = 1 (le bit de poids fort est décalé vers CF)
; En même temps, le 1 d'origine dans CF est décalé vers le bit de poids faible, formant une rotation
; Effet réel de ROL : décalage à gauche de 1 bit, le bit de poids fort va à la fois dans CF et dans le bit de poids faible
; 1000 0101 -> ROL 1 -> 0000 1011
; RCL : rotation à gauche via la retenue (CF participe à la rotation)
clc ; Mettre CF à 0
mov al, 0x85 ; 1000 0101
rcl al, 1 ; CF participe : CF bit7...bit0 -> CF
; Résultat : 0000 1010, CF = 1
; Les décalages circulaires sont couramment utilisés dans les algorithmes de chiffrement et la manipulation de bits
Utilisations pratiques des opérations logiques
Un exemple complet — implémentation d'un système simple de drapeaux binaires à l'aide d'opérations logiques :
Exemple
; Implémentation d'un système de drapeaux binaires à l'aide d'opérations logiques
section .data
flags db 0 ; 8 bits de drapeau, initialement tous à 0
; bit0 : actif ou non
; bit1 : visible ou non
; bit2 : doit être sauvegardé ou non
; bit3 : modifié ou non
FLAG_ACTIVE equ 1 ; 0000 0001
FLAG_VISIBLE equ 2 ; 0000 0010
FLAG_NEED_SAVE equ 4 ; 0000 0100
FLAG_MODIFIED equ 8 ; 0000 1000
section .text
global _start
_start:
; Définition des bits de drapeau : OR
mov al, [flags]
or al, FLAG_ACTIVE ; Mettre à 1 le bit0
or al, FLAG_VISIBLE ; Mettre à 1 le bit1
; al = 0000 0011 = 3
mov [flags], al
; Vérification des bits de drapeau : AND + TEST
test byte [flags], FLAG_ACTIVE ; Tester si le bit0 est à 1
jnz is_active ; ZF=0 signifie que le bit est 1
is_active:
; Effacement des bits de drapeau : AND + NOT
mov al, [flags]
and al, ~FLAG_VISIBLE ; Effacer le bit1 (conserver les autres bits inchangés)
; al = 0000 0001 = 1
mov [flags], al
; Basculement des bits de drapeau : XOR
mov al, [flags]
xor al, FLAG_MODIFIED ; Inverser le bit3
; S'il était 0, il devient 1, s'il était 1, il devient 0
mov eax, 1
mov ebx, 0
int 0x80
Autres extensionsLa manipulation de bits de drapeau est extrêmement courante en programmation système. Les noyaux de systèmes d'exploitation, les pilotes de périphériques et les systèmes embarqués utilisent largement cette technique pour gérer l'état.