Montaż - instrukcje arytmetyczne
Instrukcja INC
Instrukcja INC jest używana do zwiększania operandu o jeden. Działa na pojedynczym operandzie, który może znajdować się w rejestrze lub w pamięci.
Składnia
Instrukcja INC ma następującą składnię -
INC destination
Miejsce docelowe operandu może być 8-bitowym, 16-bitowym lub 32-bitowym operandem.
Przykład
INC EBX ; Increments 32-bit register
INC DL ; Increments 8-bit register
INC [count] ; Increments the count variable
Instrukcja DEC
Instrukcja DEC służy do zmniejszania wartości operandu o jeden. Działa na pojedynczym operandzie, który może znajdować się w rejestrze lub w pamięci.
Składnia
Instrukcja DEC ma następującą składnię -
DEC destination
Miejsce docelowe operandu może być 8-bitowym, 16-bitowym lub 32-bitowym operandem.
Przykład
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]
Instrukcje ADD i SUB
Instrukcje ADD i SUB są używane do wykonywania prostego dodawania / odejmowania danych binarnych w rozmiarze bajtu, słowa i słowa podwójnego, tj. Do dodawania lub odejmowania odpowiednio 8-bitowych, 16-bitowych lub 32-bitowych argumentów.
Składnia
Instrukcje ADD i SUB mają następującą składnię -
ADD/SUB destination, source
Instrukcja ADD / SUB może mieć miejsce między -
- Zarejestruj się, aby się zarejestrować
- Pamięć do zarejestrowania
- Zarejestruj się w pamięci
- Zarejestruj się na stałe dane
- Pamięć do stałych danych
Jednak, podobnie jak inne instrukcje, operacje z pamięci do pamięci nie są możliwe przy użyciu instrukcji ADD / SUB. Operacja ADD lub SUB ustawia lub usuwa przepełnienie i flagi przenoszenia.
Przykład
Poniższy przykład poprosi użytkownika o podanie dwóch cyfr, zapisze cyfry odpowiednio w rejestrze EAX i EBX, doda wartości, zapisze wynik w lokalizacji pamięci „ res ” i ostatecznie wyświetli wynik.
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
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
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
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
The sum is:
7
Instrukcja MUL / IMUL
Istnieją dwie instrukcje dotyczące mnożenia danych binarnych. Instrukcja MUL (Multiply) obsługuje dane bez znaku, a IMUL (Integer Multiply) obsługuje dane ze znakiem. Obie instrukcje mają wpływ na flagę Carry i Overflow.
Składnia
Składnia instrukcji MUL / IMUL jest następująca -
MUL/IMUL multiplier
Mnożnik w obu przypadkach będzie w akumulatorze, w zależności od rozmiaru mnożnika i mnożnika, a wygenerowany iloczyn jest również przechowywany w dwóch rejestrach w zależności od rozmiaru argumentów. Poniższa sekcja wyjaśnia instrukcje MUL w trzech różnych przypadkach -
Sr.No. | Scenariusze |
---|---|
1 | When two bytes are multiplied − Mnożnik znajduje się w rejestrze AL, a mnożnik jest bajtem w pamięci lub w innym rejestrze. Produkt jest w AX. 8 bitów produktu wysokiego rzędu jest przechowywanych w AH, a 8 bitów niskiego rzędu jest przechowywanych w AL.
|
2 | When two one-word values are multiplied − Mnożnik powinien znajdować się w rejestrze AX, a mnożnik to słowo w pamięci lub inny rejestr. Na przykład, dla instrukcji takiej jak MUL DX, musisz zapisać mnożnik w DX, a mnożnik w AX. Otrzymany iloczyn jest podwójnym słowem, które będzie wymagało dwóch rejestrów. Część najwyższego rzędu (skrajna lewa) jest przechowywana w DX, a część niższego rzędu (skrajna prawa) jest przechowywana w AX.
|
3 | When two doubleword values are multiplied − Kiedy mnoży się dwie wartości podwójnego słowa, mnożnik powinien być w EAX, a mnożnik jest wartością podwójnego słowa przechowywaną w pamięci lub w innym rejestrze. Wygenerowany produkt jest przechowywany w rejestrach EDX: EAX, tj. 32 bity wyższego rzędu są zapisywane w rejestrze EDX, a 32 bity najniższego rzędu są przechowywane w rejestrze EAX.
|
Przykład
MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH ; DL= -1
MOV AL, 0BEH ; AL = -66
IMUL DL
Przykład
Poniższy przykład mnoży 3 przez 2 i wyświetla wynik -
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
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
The result is:
6
Instrukcje DIV / IDIV
Operacja dzielenia generuje dwa elementy - a quotient i a remainder. W przypadku mnożenia przepełnienie nie występuje, ponieważ do przechowywania iloczynu używane są rejestry o podwójnej długości. Jednak w przypadku podziału może wystąpić przelanie. Procesor generuje przerwanie, jeśli wystąpi przepełnienie.
Instrukcja DIV (Divide) jest używana dla danych bez znaku, a IDIV (Integer Divide) jest używana dla danych ze znakiem.
Składnia
Format instrukcji DIV / IDIV -
DIV/IDIV divisor
Dywidenda jest akumulowana. Obie instrukcje mogą działać z 8-bitowymi, 16-bitowymi lub 32-bitowymi operandami. Operacja wpływa na wszystkie sześć flag stanu. Poniższa sekcja wyjaśnia trzy przypadki dzielenia z różnymi rozmiarami operandów -
Sr.No. | Scenariusze |
---|---|
1 | When the divisor is 1 byte − Zakłada się, że dywidenda znajduje się w rejestrze AX (16 bitów). Po podzieleniu iloraz trafia do rejestru AL, a reszta do rejestru AH.
|
2 | When the divisor is 1 word − Zakłada się, że dywidenda ma długość 32 bity i znajduje się w rejestrach DX: AX. 16 bitów wysokiego rzędu jest w DX, a 16 bitów niskiego rzędu w AX. Po podzieleniu, 16-bitowy iloraz trafia do rejestru AX, a 16-bitowa reszta trafia do rejestru DX.
|
3 | When the divisor is doubleword − Zakłada się, że dywidenda ma długość 64 bitów i jest zapisana w rejestrach EDX: EAX. 32 bity najwyższego rzędu są w EDX, a 32 bity najniższego rzędu w EAX. Po podzieleniu 32-bitowy iloraz trafia do rejestru EAX, a 32-bitowa reszta trafia do rejestru EDX.
|
Przykład
Poniższy przykład dzieli 8 przez 2. dividend 8 jest przechowywany w 16-bit AX register i divisor 2 jest przechowywany w 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
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
The result is:
4