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