Instruction IMUL dans le 8086 : Mécanique de la multiplication signée
L'instruction IMUL (Integer Multiply) du 8086/8088 effectue la multiplication signée d'opérandes 8 bits ou 16 bits. Elle est distincte de MUL (multiplication non signée). Voici l'opération précise :
Formes d'instruction (8086/8088)
| Forme | Syntaxe | Opération | Taille résultat | Drapeaux affectés |
|---|---|---|---|---|
| 8 bits | IMUL r/m8 | AL × r/m8 | 16 bits dans AX | CF, OF (mis si extension signe AH ≠ AL) ; SF, ZF, AF, PF indéfinis |
| 16 bits | IMUL r/m16 | AX × r/m16 | 32 bits dans DX:AX | CF, OF (mis si extension signe DX ≠ AX) ; SF, ZF, AF, PF indéfinis |
r/m8 = registre ou mémoire 8 bits ; r/m16 = registre ou mémoire 16 bits.
Exécution pas à pas (Exemple forme 16 bits)
- Opérandes : Source (registre/mémoire) et destination implicite AX.
- Extension de signe : Les deux opérandes traités comme entiers signés en complément à 2.
- Multiplication : L'ALU calcule AX × src comme produit signé 32 bits.
- Stockage résultat :
- 16 bits poids faible → AX
- 16 bits poids fort → DX
- Positionnement drapeaux :
- CF = OF = 1 si mot poids fort (DX) n'est pas l'extension de signe du mot poids faible (AX). C.-à-d., si résultat ne tient pas en 16 bits signés.
- CF = OF = 0 si résultat tient en 16 bits (DX = extension signe de AX).
- SF, ZF, AF, PF sont indéfinis (selon manuel Intel). Ne pas s'y fier.
Règle d'extension de signe
Pour un résultat 16 bits dans AX « correctement signé », les 16 bits poids fort (DX) doivent être tous à 0 (si positif) ou tous à 1 (si négatif) — c.-à-d. DX = AX répliqué sur 16 bits. Sinon, débordement.
Exemple : IMUL 16 bits
; AX = 0x23AF (9 135), src = 0x4567 (17 767) ; Produit = 9 135 × 17 767 = 162 300 345 = 0x09B3 0x10B9 (32 bits) ; DX:AX = 0x09B3:0x10B9 ; Comme DX (0x09B3) ≠ extension signe de AX (0x10B9 → bit signe 0 → DX devrait être 0x0000), ; CF=1, OF=1 (débordement : résultat > 32 767)
Exemple 8 bits
; AL = 0x7F (127), BL = 0x02 (2) ; IMUL BL ; AX = 0x00FA (254) → tient en 8 bits signés ? 254 > 127 → débordement. ; AH = 0x00, AL = 0xFA. AH (0x00) ≠ extension signe de AL (0xFA → bit signe 1 → AH devrait être 0xFF). ; CF=1, OF=1.
Différences clés : IMUL vs MUL
- MUL : Non signé. Traite opérandes comme positifs. CF/OF mis si résultat > taille destination (ex. AX > FFh pour 8 bits).
- IMUL : Signé. Traite opérandes comme complément à 2. CF/OF mis si résultat ne tient pas dans taille destination signée.
Extensions ultérieures (186+ / 386+)
- Deux opérandes :
IMUL r16, r/m16→ r16 = r16 × r/m16 (16 bits poids faible seulement, pas DX). - Trois opérandes :
IMUL r16, r/m16, imm16→ r16 = r/m16 × imm16. - Formes immédiates :
IMUL r16, imm8/imm16. - Ces formes tronquent à 16 bits ; CF/OF mis si bits tronqués ≠ bits signe.
Notes pratiques
- IMUL plus lent que MUL (logique signe extra). ~80–130 cycles sur 8086.
- Utilisez
CBW(AL→AX) /CWD(AX→DX:AX) avant IMUL si extension taille opérande. - Pour 8 bits × 8 bits → 16 bits en 8086, résultat toujours dans AX. DX non utilisé.
- En assembleur inline (C), utilisez intrinsèques compilateur ou built-ins (__emulu, __emuls).
IMUL est essentiel pour l'arithmétique sur entiers signés (coordonnées, physique, DSP, crypto) en code real-mode 16 bits.
