1. Arithmetic operation

We will now focus on arithmetic operations, such as additions and subtractions.
This is the first time since the beginning of the tutorial that FLAGS have been used. Therefore, I give you the picture.
image

To make additions and subtractions, we will use the following instructions:

  • ADD / SUB
  • ADC / SBB -> involves the use of the carry flag (CF)
  • INC / DEC

1.1 Example

Once is not customary, here is a sample code:

global _start
section .text
_start:
    mov rax, 0x12
    mov rbx, 0x32
    add rax, rbx
    sub rax, 0x21

    ; test carry flag
    mov rax, 0xffffffffffffffff
    add rax, 0x1
    adc rax, 0x2 ; add rax with 0x2 + 1 due to CF

    mov rax, qword [var1]
    add qword [var2], rax
    add qword [var2], 0x02

    clc ; clear carry flag
    stc ; set carry flag
    cmc ; complement carry flag

    stc
    sbb rax, 0x12

    inc rax
    dec rbx

    ; exit
    mov rax, 60
    syscall

section .data
    var1: db 0x1
    var2: dq 0xaa

1.2 Multiplication and division

We will now see how multiplications and divisions in ASM work.
To achieve them we will need the following instructions:

  • MUL / IMUL (signed)
  • DIV / IDIV (signed)

Before going further, it's interesting to look at the differences between a signed and an unsigned value.
The difference between the two is that the most significant bit serves as a bit to sign. That is, if this bit goes to 1, all the resulting values will be negative values.

Perfect. Before going into practice, it is important to understand how registers work during multiplication and division operations.

Note in the image below that if the operation is too large, the RAX register will contain the result of the operation while the RDX register contains the remainder of it.
To better understand this, nothing beats the practice.

1.2.1 Example

global _start

section .text
_start:
    mov rax, 0x12
    mov rbx, 0x2
    mul rbx

    mov rax, 0xffffffff12
    mov rbx, 0x1234556788
    mul rbx

    mov rax, 0x12
    mul byte [var1]
    mul dword [var2]

    ; exit

    mov rax, 60
    syscall

section .data
    var1: db 0x11
    var2: dq 0x12345678

I let you practice to experience divisions.

2. Logical operation

For those who have not made electronics, logical operations consist of performing bitwise operations to modify their values.

2.1. AND

Value 1 Value 2 Result
0 0 0
0 1 0
1 0 0
1 1 1

2.2. OR

Value 1 Value 2 Result
0 0 0
0 1 1
1 0 1
1 1 1

2.3. XOR

Value 1 Value 2 Result
0 0 0
0 1 1
1 0 1
1 1 0

2.4. NOT

NOT allows you to invert the bit values.

2.5. Example

global _start

section .text
_start:
    mov rax, qword [var1]
    not rax

    xor rax, rax ; set rax to 0
    mov rax, qword [var2]
    xor rax, qword [var1]

    and rax, 0x7812
    or rax, 0x1

    ; exit
    mov rax, 60
    syscall

section .data
    var1: dq 0x1111111111111111
    var2: dq 0x123456789abcdef0

3. Bit shifting

3.1. Shifting instruction

The shift instructions move a bit string (or the operand processed as a bit string) to the right or to the left, with excess bits discarded (although one or more bits may be stored in flags) . In left arithmetic shift or logical shift, the leading zeros are shifted to the low-order bit. In right arithmetic shift, the sign bit (most significant bit) is shifted to the most significant bit. In logical shift, the zeros on the right are shifted into the most significant bit.

There are several instructions for performing these operations, the most common being:

  • SHL / SAL (signed)
  • SHR / SAR (signed)

The image below is extracted from the intel manual and explains the operation of bit shifts:

It can be seen that depending on the value of the shifted bit, the carry flag can then be activated or not.
The operation is identical for shifting left and right.

The image below explains the operation of the instruction SAR:

Note that this instruction is used to perform the shift on the signed values. The first two diagrams show the operation when the value is unsigned, which does not charge the operation seen previously. On the other hand, when the value is signed, it is found that the most significant bit remains at 1, to indicate that the value is signed.

3.2. Rotation instructions

The rotation instructions are similar to the shifting instructions except that the rotation instructions are circular, with the bits being shifted from one end to the other end. Rotations can be left or right. Rotations can also use an extended bit for multi-precision rotations..

As for the shift, there are plenty of instructions but the most common ones are :

  • ROL / ROR
  • RCL / RCR

It is important to know that when you want to change position a value, it is necessary to perform a rotation of 8 bits, which corresponds to 1 byte. Otherwise we will not have the desired values.

3.3. Example

global _start

section .text
_start:

    mov rax, 0xffffffff
    sal rax, 32
    sal rax, 1

    clc
    mov rax, 0xffffffff
    shr rax, 1
    shr rax, 31

    clc
    mov rax, 0xffffffff
    sar rax, 1

    clc
    mov rax, 0xffffffffffffffff
    sar rax, 1

    clc
    mov rax, 0xabcdef0123456789
    ror rax, 8
    ror rax, 16

    ; exit

    mov rax, 60
    syscall

4. References

  1. Sign/Unsigned image Find it on slideshare
  2. Multiplication imag Find it on strchr.com
  3. Shifting Image Intel manual