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