Montagem - instruções aritméticas
A Instrução INC
A instrução INC é usada para incrementar um operando em um. Ele funciona em um único operando que pode estar em um registro ou na memória.
Sintaxe
A instrução INC tem a seguinte sintaxe -
INC destination
O destino do operando pode ser um operando de 8, 16 ou 32 bits.
Exemplo
INC EBX ; Increments 32-bit register
INC DL ; Increments 8-bit register
INC [count] ; Increments the count variable
A Instrução DEC
A instrução DEC é usada para diminuir um operando em um. Ele funciona em um único operando que pode estar em um registro ou na memória.
Sintaxe
A instrução DEC tem a seguinte sintaxe -
DEC destination
O destino do operando pode ser um operando de 8, 16 ou 32 bits.
Exemplo
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]
As instruções ADD e SUB
As instruções ADD e SUB são usadas para realizar adição / subtração simples de dados binários em tamanho de byte, palavra e palavra dupla, ou seja, para adicionar ou subtrair operandos de 8, 16 ou 32 bits, respectivamente.
Sintaxe
As instruções ADD e SUB têm a seguinte sintaxe -
ADD/SUB destination, source
A instrução ADD / SUB pode ocorrer entre -
- Cadastre-se para se registrar
- Memória para registrar
- Registre-se na memória
- Registre-se para dados constantes
- Memória para dados constantes
No entanto, como outras instruções, as operações de memória para memória não são possíveis usando as instruções ADD / SUB. Uma operação ADD ou SUB define ou limpa os sinalizadores de overflow e carry.
Exemplo
O exemplo a seguir pedirá dois dígitos ao usuário, armazenará os dígitos no registrador EAX e EBX, respectivamente, adicionará os valores, armazenará o resultado em um local de memória ' res ' e finalmente exibirá o 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
Quando o código acima é compilado e executado, ele produz o seguinte 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
Quando o código acima é compilado e executado, ele produz o seguinte resultado -
The sum is:
7
A Instrução MUL / IMUL
Existem duas instruções para multiplicar dados binários. A instrução MUL (Multiply) lida com dados não assinados e o IMUL (Integer Multiply) lida com dados assinados. Ambas as instruções afetam o sinalizador Carry e Overflow.
Sintaxe
A sintaxe para as instruções MUL / IMUL é a seguinte -
MUL/IMUL multiplier
Multiplicando em ambos os casos estará em um acumulador, dependendo do tamanho do multiplicando e do multiplicador e o produto gerado também é armazenado em dois registradores dependendo do tamanho dos operandos. A seção a seguir explica as instruções do MUL com três casos diferentes -
Sr. Não. | Cenários |
---|---|
1 | When two bytes are multiplied − O multiplicando está no registrador AL, e o multiplicador é um byte na memória ou em outro registrador. O produto está em AX. Os 8 bits de ordem superior do produto são armazenados em AH e os 8 bits de ordem inferior são armazenados em AL. |
2 | When two one-word values are multiplied − O multiplicando deve estar no registrador AX, e o multiplicador é uma palavra na memória ou outro registrador. Por exemplo, para uma instrução como MUL DX, você deve armazenar o multiplicador em DX e o multiplicando em AX. O produto resultante é uma palavra dupla, que precisará de dois registros. A parte de ordem superior (extrema esquerda) é armazenada em DX e a parte de ordem inferior (extrema direita) é armazenada em AX. |
3 | When two doubleword values are multiplied − Quando dois valores de palavra dupla são multiplicados, o multiplicando deve estar em EAX e o multiplicador é um valor de palavra dupla armazenado na memória ou em outro registro. O produto gerado é armazenado nos registradores EDX: EAX, ou seja, os 32 bits de ordem superior são armazenados no registrador EDX e os 32 bits de ordem inferior são armazenados no registrador EAX. |
Exemplo
MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH ; DL= -1
MOV AL, 0BEH ; AL = -66
IMUL DL
Exemplo
O exemplo a seguir multiplica 3 por 2 e exibe o 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
Quando o código acima é compilado e executado, ele produz o seguinte resultado -
The result is:
6
As instruções DIV / IDIV
A operação de divisão gera dois elementos - um quotient e um remainder. No caso de multiplicação, o estouro não ocorre porque registros de comprimento duplo são usados para manter o produto. No entanto, em caso de divisão, pode ocorrer estouro. O processador gera uma interrupção se ocorrer estouro.
A instrução DIV (Divide) é usada para dados sem sinal e o IDIV (Integer Divide) é usado para dados assinados.
Sintaxe
O formato da instrução DIV / IDIV -
DIV/IDIV divisor
O dividendo está em um acumulador. Ambas as instruções podem funcionar com operandos de 8, 16 ou 32 bits. A operação afeta todos os seis sinalizadores de status. A seção a seguir explica três casos de divisão com diferentes tamanhos de operando -
Sr. Não. | Cenários |
---|---|
1 | When the divisor is 1 byte − O dividendo é assumido como estando no registrador AX (16 bits). Após a divisão, o quociente vai para o registrador AL e o restante vai para o registrador AH. |
2 | When the divisor is 1 word − O dividendo é assumido como tendo 32 bits de comprimento e nos registradores DX: AX. Os 16 bits de ordem superior estão em DX e os 16 bits de ordem inferior estão em AX. Após a divisão, o quociente de 16 bits vai para o registrador AX e o restante de 16 bits vai para o registrador DX. |
3 | When the divisor is doubleword − O dividendo é assumido como tendo 64 bits de comprimento e nos registradores EDX: EAX. Os 32 bits de ordem superior estão em EDX e os 32 bits de ordem inferior estão em EAX. Após a divisão, o quociente de 32 bits vai para o registrador EAX e o restante de 32 bits vai para o registrador EDX. |
Exemplo
O exemplo a seguir divide 8 por 2. O dividend 8 é armazenado no 16-bit AX register e a divisor 2 é armazenado no 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
Quando o código acima é compilado e executado, ele produz o seguinte resultado -
The result is:
4