Assembleur 80x86 | DIV |
---|---|
INTEL 8088+, x86-64 | Division |
Syntaxe
DIV Opérande |
Paramètres
Nom | Description |
---|---|
opérande | Ce paramètre permet d'indiquer le diviseur |
Description
L'instruction DIV permet d'effectuer une division non-signée (nombre naturel). Le dividende est implicite; il est ajuster en fonction de la taille du diviseur. Le restant est toujours plus petit que le diviseur. Le type de diviseur détermine quel registre l'instruction utilisera :
Taille | Dividende | Diviseur | Quotient | Restant | Quotient maximum |
---|---|---|---|---|---|
Octet | AX | Opérande | AL | AH | 255 |
Mot | DX:AX | Opérande | AX | DX | 65 535 |
Double mot | EDX:EAX | Opérande | EAX | EDX | 232-1 |
Quadruple mot | RDX:RAX | Opérande | RAX | RDX | 264-1 |
Remarques
- Les résultats non-intégraux sont tronqués (hachés) vers 0. Le reste est toujours inférieur au diviseur en magnitude. Le dépassement de capacité est indiqué par l'exception #DE (erreur de division) plutôt que par le drapeau CF.
- En mode 64 bits, la taille de fonctionnement par défaut de l'instruction est de 32 bits. L'utilisation du préfixe REX.R permet d'accéder à des registres supplémentaires (R8 à R15). L'utilisation du préfixe REX.W favorise le fonctionnement à 64 bits. En mode 64 bits, lorsque REX.W est appliqué, l'instruction divise la valeur non signée dans RDX:RAX par l'opérande source et entrepose le quotient dans RAX, le reste dans RDX.
- La division utilisant l'opérande 64 bits n'est disponible qu'en mode 64 bits.
- Optimisation : On devrait utiliser l'instruction «AND» plutôt qu'un modulo à partir d'un DIV lorsque le nombre est une puissance 2, car il utilise beaucoup moins de cycle d'horloge qu'un DIV; ainsi, il faudra alors appliquer AND avec une comme première opérande le numérateur et comme deuxième opérande le dénominateur - 1.
Algorithme
MODULE DIV(Opérande) SI Opérande = 0 ALORS Interruption 0 SINON SI Opérande 8 bits ALORS AL ← AX ÷ Opérande AH ← AX MOD Opérande FIN SI SI Opérande 16 bits ALORS AX ← ( ( DX x 65536 ) + AX ) ÷ Opérande DX ← ( ( DX x 65536 ) + AX ) MOD Opérande FIN SI SI Opérande 32 bits ALORS EAX ← ( ( EDX x 65536 x 65536 ) + EAX ) ÷ Opérande EDX ← ( ( EDX x 65536 x 65536 ) + EAX ) MOD Opérande FIN SI FIN SI |
Mnémonique
Instruction | Opcode | Description |
---|---|---|
DIV reg/mem8 | F6h /6 | Division naturel de AX par le contenu d'un emplacement mémoire ou registre 8 bits et entrepose le quotient dans AL et restant dans AH. |
DIV reg/mem16 | F7h /6 | Division naturel de DX:AX par le contenu d'un emplacement mémoire ou registre 16 bits et entrepose le quotient dans AX et restant dans DX. |
DIV reg/mem32 | F7h /6 | Division naturel de EDX:EAX par le contenu d'un emplacement mémoire ou registre 32 bits et entrepose le quotient dans EAX et restant dans EDX. |
DIV reg/mem64 | F7h /6 | Division naturel de RDX:RAX par le contenu d'un emplacement mémoire ou registre 64 bits et entrepose le quotient dans RAX et restant dans RDX. |
Cycles d'horloge
Opérande | Cycle d'horloge | Taille en octets | |||
---|---|---|---|---|---|
8086 | 80286 | 80386 | 80486 | ||
reg8 | 80 à 90 | 14 | 14 | 16 | 2 |
reg16 | 144 à 162 | 22 | 22 | 24 | 2 |
reg32 | - | - | 38 | 40 | 2 |
mem8 | 86 à 96 (+ EA) | 17 | 17 | 16 | 2 à 4 |
mem16 | 150 à 168 (+ EA) | 25 | 25 | 24 | 2 à 4 |
mem32 | - | - | 41 | 40 | 2 à 4 |
Exceptions
Message | Mode réel | Virtuel 8086 | Mode protégé | Description |
---|---|---|---|---|
#DE(Division par zéro) | X | X | X | L'opérande de diviseur vaut 0. |
X | X | X | Le quotient est trop large pour le registre désigné. | |
#SS(Pile) | X | X | X | Une adresse mémoire dépasse la limite du segment de pile ou n'est pas canonique |
#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 | Un segment de données nulle est utilisé comme référence mémoire | |||
#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é |
Exemples
L'exemple suivant permet de diviser un mot dans le registre AX avec un octet dans le registre BL. Le résultat du quotient est envoyé dans le registre AL et le restant dans AH :
- DIV BL
Voici quelques exemples typiques de l'utilisation de cet opérateur :
- .MODEL small
- .STACK 100h
- .DATA
- Message1 DB 'div(-81,9) = ','$'
- Message2 DB 'div(15,3) = ','$'
- Message3 DB 'div(16,3) = ','$'
- Message4 DB 'div(17,3) = ','$'
- Message5 DB 'div(18,3) = ','$'
- Message6 DB 'div(19,3) = ','$'
- Message7 DB 'div(0,1) = ','$'
- CRLF DB 13,10,'$'
- .CODE
- PrintDigit PROC NEAR
- OR AX,AX
- JNS Positif
- PUSH AX
- MOV AH,02h
- MOV DL,'-'
- INT 21h
- POP AX
- NEG AX
- Positif:
- MOV BX,10
- XOR CX,CX
- NextDigit:
- XOR DX,DX
- DIV BX
- PUSH DX
- INC CX
- OR AX,AX
- JNZ NextDigit
- PrintOneDigit:
- POP AX
- ADD AL,48
- MOV DL,AL
- MOV AH,02h
- INT 21h
- LOOP PrintOneDigit
- RET
- ENDP
-
- .startup
-
- ; div(-81,9)
- MOV AX,@data
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET Message1
- INT 21h
- MOV AL,81
- XOR AH,AH
- NEG AH
- MOV CX,9
- DIV CL
- NEG AX
- CALL PrintDigit
- MOV AH,9
- MOV DX,OFFSET CRLF
- INT 21h
-
- ; div(15,3)
- MOV AX,@data
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET Message2
- INT 21h
- MOV AX,15
- XOR DX,DX
- MOV CX,3
- DIV CX
- CALL PrintDigit
- MOV AH,9
- MOV DX,OFFSET CRLF
- INT 21h
-
- ; div(16,3)
- MOV AX,@data
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET Message3
- INT 21h
- MOV AX,16
- XOR DX,DX
- MOV CX,3
- DIV CX
- CALL PrintDigit
- MOV AH,9
- MOV DX,OFFSET CRLF
- INT 21h
-
- ; div(17,3)
- MOV AX,@data
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET Message4
- INT 21h
- MOV AX,17
- XOR DX,DX
- MOV CX,3
- DIV CX
- CALL PrintDigit
- MOV AH,9
- MOV DX,OFFSET CRLF
- INT 21h
-
- ; div(18,3)
- MOV AX,@data
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET Message5
- INT 21h
- MOV AX,18
- XOR DX,DX
- MOV CX,3
- DIV CX
- CALL PrintDigit
- MOV AH,9
- MOV DX,OFFSET CRLF
- INT 21h
-
- ; div(19,3)
- MOV AX,@data
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET Message6
- INT 21h
- MOV AX,19
- XOR DX,DX
- MOV CX,3
- DIV CX
- CALL PrintDigit
- MOV AH,9
- MOV DX,OFFSET CRLF
- INT 21h
-
- ; div(0,1)
- MOV AX,@data
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET Message7
- INT 21h
- MOV AX,0
- XOR DX,DX
- MOV CX,1
- DIV CX
- CALL PrintDigit
- MOV AH,9
- MOV DX,OFFSET CRLF
- INT 21h
-
-
- MOV AX,4C00h
- INT 21h
- END
on obtiendra le résultat suivant :
div(-81,9) = -9div(15,3) = 5
div(16,3) = 5
div(17,3) = 5
div(18,3) = 6
div(19,3) = 6
div(0,1) = 0
Voir également
Instruction assembleur 80x86 - Instruction MUL
Instruction assembleur 80x86 - Instruction IDIV
Références
Le livre d'Or PC, Martin Althaus, 1992, ISBN: 2-7361-0934-1, page 810
Assembleur Facile, Philippe Mercier, 1990, ISBN: 2-501-01176-7, page 404
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 109.
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 358 à 360.