Assemblage - Instructions arithmétiques
L'instruction INC
L'instruction INC est utilisée pour incrémenter un opérande de un. Il fonctionne sur un seul opérande qui peut être dans un registre ou en mémoire.
Syntaxe
L'instruction INC a la syntaxe suivante -
INC destination
La destination de l' opérande peut être un opérande 8 bits, 16 bits ou 32 bits.
Exemple
INC EBX ; Increments 32-bit register
INC DL ; Increments 8-bit register
INC [count] ; Increments the count variable
L'instruction DEC
L'instruction DEC est utilisée pour décrémenter un opérande de un. Il fonctionne sur un seul opérande qui peut être dans un registre ou en mémoire.
Syntaxe
L'instruction DEC a la syntaxe suivante -
DEC destination
La destination de l' opérande peut être un opérande 8 bits, 16 bits ou 32 bits.
Exemple
segment .data
count dw 0
value db 15
segment .text
inc [count]
dec [value]
mov ebx, count
inc word [ebx]
mov esi, value
dec byte [esi]
Les instructions ADD et SUB
Les instructions ADD et SUB sont utilisées pour effectuer une simple addition / soustraction de données binaires en octets, en mot et en double mot, c'est-à-dire pour ajouter ou soustraire des opérandes de 8 bits, 16 bits ou 32 bits, respectivement.
Syntaxe
Les instructions ADD et SUB ont la syntaxe suivante -
ADD/SUB destination, source
L'instruction ADD / SUB peut avoir lieu entre -
- Inscrivez-vous pour vous inscrire
- Mémoire à enregistrer
- Enregistrez-vous en mémoire
- S'inscrire aux données constantes
- Mémoire aux données constantes
Cependant, comme les autres instructions, les opérations de mémoire à mémoire ne sont pas possibles à l'aide des instructions ADD / SUB. Une opération ADD ou SUB définit ou efface les indicateurs de dépassement de capacité et de report.
Exemple
L'exemple suivant demandera deux chiffres à l'utilisateur, stockera les chiffres dans le registre EAX et EBX, respectivement, ajoutera les valeurs, stockera le résultat dans un emplacement de mémoire « res » et affichera finalement le résultat.
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
segment .data
msg1 db "Enter a digit ", 0xA,0xD
len1 equ $- msg1
msg2 db "Please enter a second digit", 0xA,0xD
len2 equ $- msg2
msg3 db "The sum is: "
len3 equ $- msg3
segment .bss
num1 resb 2
num2 resb 2
res resb 1
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
; moving the first number to eax register and second number to ebx
; and subtracting ascii '0' to convert it into a decimal number
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
; add eax and ebx
add eax, ebx
; add '0' to to convert the sum from decimal to ASCII
add eax, '0'
; storing the sum in memory location res
mov [res], eax
; print the sum
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, res
mov edx, 1
int 0x80
exit:
mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -
Enter a digit:
3
Please enter a second digit:
4
The sum is:
7
The program with hardcoded variables −
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax,'3'
sub eax, '0'
mov ebx, '4'
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,sum
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The sum is:", 0xA,0xD
len equ $ - msg
segment .bss
sum resb 1
Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -
The sum is:
7
L'instruction MUL / IMUL
Il existe deux instructions pour multiplier les données binaires. L'instruction MUL (Multiply) gère les données non signées et IMUL (Integer Multiply) gère les données signées. Les deux instructions affectent l'indicateur Carry et Overflow.
Syntaxe
La syntaxe des instructions MUL / IMUL est la suivante -
MUL/IMUL multiplier
Le multiplicande dans les deux cas sera dans un accumulateur, en fonction de la taille du multiplicande et du multiplicateur et le produit généré est également stocké dans deux registres en fonction de la taille des opérandes. La section suivante explique les instructions MUL avec trois cas différents -
N ° Sr. | Scénarios |
---|---|
1 | When two bytes are multiplied − Le multiplicande est dans le registre AL et le multiplicateur est un octet dans la mémoire ou dans un autre registre. Le produit est en AX. Les 8 bits de poids fort du produit sont stockés dans AH et les 8 bits de poids faible sont stockés dans AL. |
2 | When two one-word values are multiplied − Le multiplicande doit être dans le registre AX et le multiplicateur est un mot en mémoire ou un autre registre. Par exemple, pour une instruction comme MUL DX, vous devez stocker le multiplicateur dans DX et le multiplicande dans AX. Le produit résultant est un double mot, qui aura besoin de deux registres. La partie d'ordre supérieur (la plus à gauche) est stockée dans DX et la partie d'ordre inférieur (la plus à droite) est stockée dans AX. |
3 | When two doubleword values are multiplied − Lorsque deux valeurs de mot double sont multipliées, le multiplicande doit être en EAX et le multiplicateur est une valeur de mot double stockée en mémoire ou dans un autre registre. Le produit généré est stocké dans les registres EDX: EAX, c'est-à-dire que les 32 bits de poids fort sont stockés dans le registre EDX et les 32 bits de poids faible sont stockés dans le registre EAX. |
Exemple
MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH ; DL= -1
MOV AL, 0BEH ; AL = -66
IMUL DL
Exemple
L'exemple suivant multiplie 3 par 2 et affiche le résultat -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov al,'3'
sub al, '0'
mov bl, '2'
sub bl, '0'
mul bl
add al, '0'
mov [res], al
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,res
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1
Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -
The result is:
6
Les instructions DIV / IDIV
L'opération de division génère deux éléments - un quotient et un remainder. En cas de multiplication, le débordement ne se produit pas car des registres à double longueur sont utilisés pour conserver le produit. Cependant, en cas de division, un débordement peut se produire. Le processeur génère une interruption en cas de dépassement de capacité.
L'instruction DIV (Divide) est utilisée pour les données non signées et l'IDIV (Integer Divide) est utilisée pour les données signées.
Syntaxe
Le format de l'instruction DIV / IDIV -
DIV/IDIV divisor
Le dividende est dans un accumulateur. Les deux instructions peuvent fonctionner avec des opérandes 8 bits, 16 bits ou 32 bits. L'opération affecte les six indicateurs d'état. La section suivante explique trois cas de division avec une taille d'opérande différente -
N ° Sr. | Scénarios |
---|---|
1 | When the divisor is 1 byte − Le dividende est supposé être dans le registre AX (16 bits). Après la division, le quotient va au registre AL et le reste va au registre AH. |
2 | When the divisor is 1 word − Le dividende est supposé avoir une longueur de 32 bits et dans les registres DX: AX. Les 16 bits de poids fort sont en DX et les 16 bits de poids faible sont en AX. Après la division, le quotient 16 bits va au registre AX et le reste 16 bits va au registre DX. |
3 | When the divisor is doubleword − Le dividende est supposé avoir une longueur de 64 bits et dans les registres EDX: EAX. Les 32 bits de poids fort sont en EDX et les 32 bits de poids faible sont en EAX. Après la division, le quotient 32 bits va au registre EAX et le reste 32 bits va au registre EDX. |
Exemple
L'exemple suivant divise 8 par 2. Le dividend 8 est stocké dans le 16-bit AX register et le divisor 2 est stocké dans le 8-bit BL register.
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ax,'8'
sub ax, '0'
mov bl, '2'
sub bl, '0'
div bl
add ax, '0'
mov [res], ax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,res
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1
Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -
The result is:
4