Assembly - Istruzioni aritmetiche
L'istruzione INC
L'istruzione INC viene utilizzata per incrementare di uno un operando. Funziona su un singolo operando che può essere in un registro o in memoria.
Sintassi
L'istruzione INC ha la seguente sintassi:
INC destination
La destinazione dell'operando potrebbe essere un operando a 8 bit, 16 bit o 32 bit.
Esempio
INC EBX ; Increments 32-bit register
INC DL ; Increments 8-bit register
INC [count] ; Increments the count variable
L'istruzione DEC
L'istruzione DEC viene utilizzata per decrementare un operando di uno. Funziona su un singolo operando che può essere in un registro o in memoria.
Sintassi
L'istruzione DEC ha la seguente sintassi:
DEC destination
La destinazione dell'operando potrebbe essere un operando a 8 bit, 16 bit o 32 bit.
Esempio
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]
Le istruzioni ADD e SUB
Le istruzioni ADD e SUB vengono utilizzate per eseguire semplici addizioni / sottrazioni di dati binari in dimensioni di byte, parola e doppia parola, cioè per aggiungere o sottrarre operandi a 8 bit, 16 bit o 32 bit, rispettivamente.
Sintassi
Le istruzioni ADD e SUB hanno la seguente sintassi:
ADD/SUB destination, source
L'istruzione ADD / SUB può avvenire tra -
- Registrati per registrarti
- Memoria da registrare
- Registrati in memoria
- Registrati a dati costanti
- Memoria a dati costanti
Tuttavia, come altre istruzioni, le operazioni da memoria a memoria non sono possibili utilizzando le istruzioni ADD / SUB. Un'operazione ADD o SUB imposta o cancella i flag di overflow e carry.
Esempio
Il seguente esempio chiederà due cifre all'utente, memorizzerà le cifre rispettivamente nel registro EAX e EBX, aggiungerà i valori, memorizzerà il risultato in una posizione di memoria " res " e infine visualizzerà il risultato.
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 il codice precedente viene compilato ed eseguito, produce il seguente risultato:
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 il codice precedente viene compilato ed eseguito, produce il seguente risultato:
The sum is:
7
L'istruzione MUL / IMUL
Sono disponibili due istruzioni per moltiplicare i dati binari. L'istruzione MUL (Multiply) gestisce i dati senza segno e l'IMUL (Integer Multiply) gestisce i dati con segno. Entrambe le istruzioni influenzano il flag Carry e Overflow.
Sintassi
La sintassi per le istruzioni MUL / IMUL è la seguente:
MUL/IMUL multiplier
Il moltiplicando in entrambi i casi sarà in un accumulatore, a seconda della dimensione del moltiplicando e del moltiplicatore e anche il prodotto generato viene memorizzato in due registri a seconda della dimensione degli operandi. La sezione seguente spiega le istruzioni MUL con tre diversi casi:
Sr.No. | Scenari |
---|---|
1 | When two bytes are multiplied − Il moltiplicando si trova nel registro AL e il moltiplicatore è un byte nella memoria o in un altro registro. Il prodotto è in AX. Gli 8 bit di ordine superiore del prodotto vengono memorizzati in AH e gli 8 bit di ordine inferiore vengono memorizzati in AL.
|
2 | When two one-word values are multiplied − Il moltiplicando dovrebbe essere nel registro AX e il moltiplicatore è una parola in memoria o un altro registro. Ad esempio, per un'istruzione come MUL DX, è necessario memorizzare il moltiplicatore in DX e il moltiplicando in AX. Il prodotto risultante è una doppia parola, che richiederà due registri. La parte di ordine superiore (più a sinistra) viene memorizzata in DX e la parte di ordine inferiore (più a destra) viene archiviata in AX.
|
3 | When two doubleword values are multiplied − Quando due valori di doppia parola vengono moltiplicati, il moltiplicando dovrebbe essere in EAX e il moltiplicatore è un valore di doppia parola archiviato in memoria o in un altro registro. Il prodotto generato viene memorizzato nei registri EDX: EAX, ovvero i 32 bit di ordine alto vengono memorizzati nel registro EDX ei 32 bit di ordine basso vengono memorizzati nel registro EAX.
|
Esempio
MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH ; DL= -1
MOV AL, 0BEH ; AL = -66
IMUL DL
Esempio
L'esempio seguente moltiplica 3 per 2 e visualizza il risultato:
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 il codice precedente viene compilato ed eseguito, produce il seguente risultato:
The result is:
6
Le istruzioni DIV / IDIV
L'operazione di divisione genera due elementi: a quotient e a remainder. In caso di moltiplicazione, l'overflow non si verifica perché i registri a doppia lunghezza vengono utilizzati per mantenere il prodotto. Tuttavia, in caso di divisione, potrebbe verificarsi un trabocco. Il processore genera un interrupt se si verifica un overflow.
L'istruzione DIV (Divide) viene utilizzata per i dati senza segno e IDIV (Integer Divide) viene utilizzata per i dati con segno.
Sintassi
Il formato per l'istruzione DIV / IDIV -
DIV/IDIV divisor
Il dividendo è in un accumulatore. Entrambe le istruzioni possono funzionare con operandi a 8 bit, 16 bit o 32 bit. L'operazione influisce su tutti e sei i flag di stato. La sezione seguente spiega tre casi di divisione con diverse dimensioni di operandi:
Sr.No. | Scenari |
---|---|
1 | When the divisor is 1 byte − Si presume che il dividendo sia nel registro AX (16 bit). Dopo la divisione, il quoziente va al registro AL e il resto va al registro AH.
|
2 | When the divisor is 1 word − Si presume che il dividendo sia lungo 32 bit e nei registri DX: AX. I 16 bit di ordine superiore sono in DX e i 16 bit di ordine inferiore sono in AX. Dopo la divisione, il quoziente di 16 bit va al registro AX e il resto di 16 bit va al registro DX.
|
3 | When the divisor is doubleword − Si presume che il dividendo sia lungo 64 bit e nei registri EDX: EAX. I 32 bit di ordine superiore sono in EDX ei 32 bit di ordine inferiore sono in EAX. Dopo la divisione, il quoziente a 32 bit va al registro EAX e il resto a 32 bit va al registro EDX.
|
Esempio
L'esempio seguente divide 8 per 2. Il file dividend 8 è memorizzato nel file 16-bit AX register e il divisor 2 è memorizzato nel file 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 il codice precedente viene compilato ed eseguito, produce il seguente risultato:
The result is:
4