ARITHMETIC OPERATIONS
ADD Operation
The add
instruction is used to perform addition operations.
section .data
section .text
global _start
_start:
mov eax, 2 ; Load value 5 into eax
mov ebx, 3 ; Load value 3 into ebx
add eax, ebx ; Add ebx to eax
This instruction adds the value in ebx
to eax
and stores the result in eax
. So, after this operation, eax
should contain the sum of the two numbers 5
. Also, I can use a number like 2
in binary as 0b00000010
and in hexadecimal as 0x02
.
Handling Carry Flag
The Carry Flag CF
is another crucial aspect, especially when dealing with arithmetic operations involving limited register sizes. Consider a scenario where the result exceeds the capacity of the destination register.
section .data
section .text
global _start
_start:
mov al, 0xFF ; Load value 255 into al
mov bl, 1 ; Load value 1 into bl
add al, bl ; Add 1 to al
In this case, the result of the addition operation is 256
, which is too large to fit into the al
register. In such cases, the extra bits are carried over and stored in the CF
of the EFLAGS register. I can utilize the adc
instruction to incorporate this carry into subsequent operations.
ADC Operation
The adc
(add with carry) instruction is used to perform addition operations with a carry.
section .data
section .text
global _start
_start:
mov al, 0xFF ; Load value 255 into al
mov bl, 1 ; Load value 1 into bl
add al, bl ; Add 1 to al
adc al, 0 ; Add the carry flag to the result
In this case, the adc
instruction adds the value in the CF
to the result of the previous addition operation. This allows us to handle scenarios where the result exceeds the capacity of the destination register and carry over the extra bits.
SUB Operation
The sub
instruction is used to perform subtraction operations.
section .data
section .text
global _start
_start:
mov al, 5 ; Load value 5 into al
mov bl, 3 ; Load value 3 into bl
sub al, bl ; Subtract 3 from 5
This instruction subtracts the value in bl
from al
and stores the result in al
. So, after this operation, al
should contain the difference of the two numbers 2
.
Now, as an example, letβs flip the numbers and see what happens:
section .data
section .text
global _start
_start:
mov al, 3 ; Load value 3 into al
mov bl, 5 ; Load value 5 into bl
sub al, bl ; Subtract 5 from 3
In this case, the result of the subtraction operation is -2
, which is a negative number. The SF
(Sign Flag) in the EFLAGS register will be set to 1
to indicate that the result is negative.
Another example, what if I subtract a negative number with a positive number -2 + 2
:
section .data
section .text
global _start
_start:
mov eax, 3 ; Load value 5 into eax
mov ebx, 5 ; Load value 2 into ebx
sub eax, ebx ; Subtract 2 from 5
mov ebx, 2 ; Load value 2 into ebx
add eax, ebx ; Add -2 to 2
In this case, the result of the subtraction operation is 0
, which is the sum of the two numbers. The ZF
(Zero Flag) in the EFLAGS register will be set to 1
to indicate that the result is zero.
MUL Operation
The mul
instruction is used to perform multiplication operations, primarily for unsigned integers.
section .data
section .text
global _start
_start:
mov al, 2 ; Load value 5 into al
mov bl, 3 ; Load value 3 into bl
mul bl ; Multiply al by bl
In this case, the mul
instruction multiplies the value in bl
by al
and stores the result in al
. So, after this operation, al
should contain the product of the two numbers 6
. The register a
is a special register called the accumulator, itβs used for multiplication as the default destination for the operation.
In multiplication, itβs interesting because it only requires one operand, the other operand is implicitly the al
register. The result of the multiplication operation is stored in the pair of registers ax
and dx
. The ax
register contains the lower 16 bits of the result, while the dx
register contains the higher 16 bits.
Letβs see another example with mul
, where I multiply two unsigned numbers but the result is too large to fit in the ax
register:
section .data
section .text
global _start
_start:
mov al, 0xFF ; Load value 255 into al
mov bl, 2 ; Load value 2 into bl
mul bl ; Multiply al by bl
In this case, the result of the multiplication operation is 510
, which is too large to fit into the al
register. The extra bits are stored in the ax
register.
IMUL Operation
The imul
instruction is used to perform multiplication operations, primarily for signed integers.
Now, letβs see an example with imul
where I multiply two unsigned numbers:
section .data
section .text
global _start
_start:
mov al, 0xFF ; Load value 255 (unsigned) into al = -1 (signed)
mov bl, 2 ; Load value 2 (unsigned) into bl = 2 (signed)
imul bl ; Multiply al by bl
int 80h ; Interrupt
al
in this case will be equal to -2
. Even tho I used unsigned numbers, the program assumes the values are signed because of imul
, so the result of the multiplication operation is -2
, which is correct: 2 * -1 = -2
.
DIV Operation
The div
instruction is used to perform division operations.
section .data
section .text
global _start
_start:
mov eax, 11 ; Load value 11 into eax
mov ecx, 2 ; Load value 2 into ecx
div ecx ; Divide eax by ecx = 5 remainder 1
int 80h ; Interrupt
In this case, the div
instruction divides the value in eax
by ecx
and stores the quotient in eax
and the remainder in edx
. So, after this operation, eax
should contain the quotient 5
and edx
should contain the remainder 1
. edx
and not ecx
because div
uses edx:eax
as the dividend.
IDIV Operation
The idiv
instruction is used to perform division operations, primarily for signed integers.
section .data
section .text
global _start
_start:
mov eax, 0xff ; Load value 255 (unsigned) into eax = -1 (signed)
mov ecx, 2 ; Load value 2 into ecx
idiv ecx ; Divide eax by ecx = -1 remainder 1
int 80h ; Interrupt
In this case, the idiv
instruction divides the value in eax
by ecx
and stores the quotient in eax
and the remainder in edx
. So, after this operation, eax
should contain the quotient -1
and edx
should contain the remainder 1
.