Ensamblaje - Instrucciones aritméticas

La instrucción INC

La instrucción INC se utiliza para incrementar un operando en uno. Funciona en un solo operando que puede estar en un registro o en la memoria.

Sintaxis

La instrucción INC tiene la siguiente sintaxis:

INC destination

El destino del operando podría ser un operando de 8, 16 o 32 bits.

Ejemplo

INC EBX	     ; Increments 32-bit register
INC DL       ; Increments 8-bit register
INC [count]  ; Increments the count variable

La instrucción DEC

La instrucción DEC se utiliza para reducir un operando en uno. Funciona en un solo operando que puede estar en un registro o en la memoria.

Sintaxis

La instrucción DEC tiene la siguiente sintaxis:

DEC destination

El destino del operando podría ser un operando de 8, 16 o 32 bits.

Ejemplo

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]

Las instrucciones ADD y SUB

Las instrucciones ADD y SUB se utilizan para realizar sumas / restas simples de datos binarios en tamaño de bytes, palabras y palabras dobles, es decir, para sumar o restar operandos de 8, 16 o 32 bits, respectivamente.

Sintaxis

Las instrucciones ADD y SUB tienen la siguiente sintaxis:

ADD/SUB	destination, source

La instrucción ADD / SUB puede tener lugar entre -

  • Regístrese para registrarse
  • Memoria para registrar
  • Registrarse en la memoria
  • Registrarse en datos constantes
  • Memoria para datos constantes

Sin embargo, al igual que otras instrucciones, las operaciones de memoria a memoria no son posibles utilizando las instrucciones ADD / SUB. Una operación ADD o SUB establece o borra las banderas de desbordamiento y acarreo.

Ejemplo

El siguiente ejemplo pedirá dos dígitos al usuario, almacenará los dígitos en el registro EAX y EBX, respectivamente, sumará los valores, almacenará el resultado en una ubicación de memoria ' res ' y finalmente mostrará el resultado.

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

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

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

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

The sum is:
7

La instrucción MUL / IMUL

Hay dos instrucciones para multiplicar datos binarios. La instrucción MUL (Multiplicar) maneja datos sin firmar y la IMUL (Multiplicar enteros) maneja datos firmados. Ambas instrucciones afectan a la bandera de transporte y desbordamiento.

Sintaxis

La sintaxis de las instrucciones MUL / IMUL es la siguiente:

MUL/IMUL multiplier

Multiplicando en ambos casos estará en un acumulador, dependiendo del tamaño del multiplicando y el multiplicador y el producto generado también se almacena en dos registros dependiendo del tamaño de los operandos. La siguiente sección explica las instrucciones MUL con tres casos diferentes:

No Señor. Escenarios
1

When two bytes are multiplied −

El multiplicando está en el registro AL y el multiplicador es un byte en la memoria o en otro registro. El producto está en AX. Los 8 bits de orden superior del producto se almacenan en AH y los 8 bits de orden inferior se almacenan en AL.

2

When two one-word values are multiplied −

El multiplicando debe estar en el registro AX, y el multiplicador es una palabra en la memoria u otro registro. Por ejemplo, para una instrucción como MUL DX, debe almacenar el multiplicador en DX y el multiplicando en AX.

El producto resultante es una palabra doble, que necesitará dos registros. La parte de orden superior (más a la izquierda) se almacena en DX y la parte de orden inferior (más a la derecha) se almacena en AX.

3

When two doubleword values are multiplied −

Cuando se multiplican dos valores de dos palabras, el multiplicando debe estar en EAX y el multiplicador es un valor de dos palabras almacenado en la memoria o en otro registro. El producto generado se almacena en los registros EDX: EAX, es decir, los 32 bits de orden superior se almacenan en el registro EDX y los 32 bits de orden inferior se almacenan en el registro EAX.

Ejemplo

MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH	; DL= -1
MOV AL, 0BEH	; AL = -66
IMUL DL

Ejemplo

El siguiente ejemplo multiplica 3 por 2 y muestra el resultado:

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

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

The result is:
6

Las instrucciones DIV / IDIV

La operación de división genera dos elementos: un quotient y un remainder. En caso de multiplicación, no se produce un desbordamiento porque se utilizan registros de doble longitud para mantener el producto. Sin embargo, en caso de división, puede producirse un desbordamiento. El procesador genera una interrupción si se produce un desbordamiento.

La instrucción DIV (Divide) se usa para datos sin firmar y el IDIV (Integer Divide) se usa para datos firmados.

Sintaxis

El formato de la instrucción DIV / IDIV -

DIV/IDIV	divisor

El dividendo está en un acumulador. Ambas instrucciones pueden funcionar con operandos de 8, 16 o 32 bits. La operación afecta a las seis banderas de estado. La siguiente sección explica tres casos de división con diferente tamaño de operando:

No Señor. Escenarios
1

When the divisor is 1 byte −

Se supone que el dividendo está en el registro AX (16 bits). Después de la división, el cociente va al registro AL y el resto al registro AH.

2

When the divisor is 1 word −

Se supone que el dividendo tiene una longitud de 32 bits y está en los registros DX: AX. Los 16 bits de orden superior están en DX y los 16 bits de orden inferior están en AX. Después de la división, el cociente de 16 bits va al registro AX y el resto de 16 bits al registro DX.

3

When the divisor is doubleword −

Se supone que el dividendo tiene una longitud de 64 bits y está en los registros EDX: EAX. Los 32 bits de orden superior están en EDX y los 32 bits de orden inferior están en EAX. Después de la división, el cociente de 32 bits va al registro EAX y el resto de 32 bits va al registro EDX.

Ejemplo

El siguiente ejemplo divide 8 por 2. El dividend 8 se almacena en el 16-bit AX register y el divisor 2 se almacena en el 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

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

The result is:
4