Detailed Explanation of Arithmetic Instructions in Assembly Language

Overview of Arithmetic Instructions

Assembly language provides a set of arithmetic instructions to perform basic mathematical operations, including addition, subtraction, multiplication, and division. These instructions can directly manipulate registers, data in memory, and immediate values.

Basic Arithmetic Instructions

1. INC and DEC Instructions

INC (Increment) – Increment Instruction

Increases the operand by 1.

section .data
    count dd 5
    value db 10

section .text
    global _start

_start:
    ; Incrementing registers
    mov eax, 10
    inc eax          ; EAX = 11

    mov bx, 100
    inc bx           ; BX = 101

    mov cl, 50
    inc cl           ; CL = 51

    ; Incrementing memory
    inc dword [count]    ; count = 6
    inc byte [value]     ; value = 11

    ; Incrementing via indirect addressing
    mov esi, count
    inc dword [esi]      ; count = 7

    mov edi, value
    inc byte [edi]       ; value = 12

    mov eax, 1
    mov ebx, 0
    int 0x80

DEC (Decrement) – Decrement Instruction

Decreases the operand by 1.

section .data
    counter dd 10
    temp db 5

section .text
    global _start

_start:
    ; Decrementing registers
    mov ecx, 20
    dec ecx          ; ECX = 19

    mov dx, 100
    dec dx           ; DX = 99

    mov al, 1
    dec al           ; AL = 0

    ; Decrementing memory
    dec dword [counter]  ; counter = 9
    dec byte [temp]      ; temp = 4

    ; Loop counter example
    mov ecx, 5
loop_start:
    ; Loop body code...
    dec ecx
    jnz loop_start   ; Continue loop while ECX is not 0

    mov eax, 1
    mov ebx, 0
    int 0x80

2. ADD and SUB Instructions

ADD (Addition) – Addition Instruction

section .data
    num1 dd 100
    num2 dd 50
    result dd 0

section .text
    global _start

_start:
    ; Register to register addition
    mov eax, 10
    mov ebx, 20
    add eax, ebx     ; EAX = 30

    ; Immediate to register addition
    mov ecx, 5
    add ecx, 15      ; ECX = 20

    ; Memory to register addition
    mov edx, [num1]
    add edx, [num2]  ; EDX = 150

    ; Register to memory addition
    mov eax, 25
    add [result], eax ; result = 25

    ; Immediate to memory addition
    add dword [result], 75 ; result = 100

    ; 8-bit, 16-bit, 32-bit addition examples
    mov al, 200
    add al, 100      ; AL = 44 (with carry, since 300 > 255)

    mov ax, 30000
    add ax, 20000    ; AX = 50000

    mov eax, 1000000
    add eax, 2000000 ; EAX = 3000000

    mov eax, 1
    mov ebx, 0
    int 0x80

SUB (Subtraction) – Subtraction Instruction

section .data
    a dd 100
    b dd 75
    diff dd 0

section .text
    global _start

_start:
    ; Register to register subtraction
    mov eax, 50
    mov ebx, 30
    sub eax, ebx     ; EAX = 20

    ; Immediate subtraction
    mov ecx, 100
    sub ecx, 25      ; ECX = 75

    ; Memory subtraction
    mov edx, [a]
    sub edx, [b]     ; EDX = 25

    ; Borrow example
    mov al, 10
    sub al, 20       ; AL = 246 (with borrow)

    ; Comparison operation (actually subtraction, but does not save result)
    mov eax, 100
    cmp eax, 50      ; Set flags, but does not modify EAX

    mov eax, 1
    mov ebx, 0
    int 0x80

Comprehensive Example: Addition Calculator

section .data
    ; Prompt messages
    msg1 db "Enter first number: ", 0
    len1 equ $ - msg1

    msg2 db "Enter second number: ", 0
    len2 equ $ - msg2

    msg3 db "The sum is: ", 0
    len3 equ $ - msg3

    newline db 0xA

section .bss
    num1 resb 10
    num2 resb 10
    result resb 10
    buffer resb 10

section .text
    global _start

_start:
    ; Display first prompt
    mov eax, 4
    mov ebx, 1
    mov ecx, msg1
    mov edx, len1
    int 0x80

    ; Read first number
    mov eax, 3
    mov ebx, 0
    mov ecx, num1
    mov edx, 10
    int 0x80

    ; Display second prompt
    mov eax, 4
    mov ebx, 1
    mov ecx, msg2
    mov edx, len2
    int 0x80

    ; Read second number
    mov eax, 3
    mov ebx, 0
    mov ecx, num2
    mov edx, 10
    int 0x80

    ; Convert and add
    call ascii_to_int
    mov ebx, eax        ; Save first number

    mov ecx, num2
    call ascii_to_int   ; Second number in EAX

    add eax, ebx        ; Add

    ; Display result
    mov eax, 4
    mov ebx, 1
    mov ecx, msg3
    mov edx, len3
    int 0x80

    call int_to_ascii
    mov eax, 4
    mov ebx, 1
    mov ecx, buffer
    mov edx, 10
    int 0x80

    ; New line
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    ; Exit
    mov eax, 1
    mov ebx, 0
    int 0x80

; ASCII to integer subroutine
ascii_to_int:
    xor eax, eax        ; Clear EAX
    xor ebx, ebx        ; Clear EBX

.convert_loop:
    mov bl, [ecx]       ; Read character
    cmp bl, 0xA         ; New line
    je .done
    cmp bl, 0           ; End of string
    je .done

    sub bl, '0'         ; Convert to number
    imul eax, 10        ; EAX *= 10
    add eax, ebx        ; EAX += number

    inc ecx             ; Next character
    jmp .convert_loop

.done:
    ret

; Integer to ASCII subroutine
int_to_ascii:
    mov edi, buffer + 9
    mov byte [edi], 0
    mov ecx, 10

    test eax, eax
    jnz .convert
    mov byte [buffer], '0'
    mov byte [buffer+1], 0
    ret

.convert:
    dec edi
    xor edx, edx
    div ecx
    add dl, '0'
    mov [edi], dl
    test eax, eax
    jnz .convert

    ; Move to buffer start
    mov esi, edi
    mov edi, buffer
    mov ecx, 10
    rep movsb

    ret

Multiplication and Division Instructions

3. MUL and IMUL Instructions

MUL (Unsigned Multiply) – Unsigned Multiplication

section .data
    result8  dw 0
    result16 dd 0
    result32 dq 0

section .text
    global _start

_start:
    ; 8-bit multiplication: AL * 8-bit operand = AX
    mov al, 10
    mov bl, 5
    mul bl              ; AX = 50

    mov [result8], ax   ; Save result

    ; 16-bit multiplication: AX * 16-bit operand = DX:AX
    mov ax, 1000
    mov bx, 100
    mul bx              ; DX:AX = 100000

    ; Save 32-bit result
    shl edx, 16
    mov dx, ax
    mov [result16], edx

    ; 32-bit multiplication: EAX * 32-bit operand = EDX:EAX
    mov eax, 100000
    mov ebx, 1000
    mul ebx             ; EDX:EAX = 100000000

    ; Save 64-bit result
    mov dword [result32], eax
    mov dword [result32+4], edx

    ; Memory operand multiplication
    mov eax, 50
    mul dword [result16] ; EAX * [result16]

    mov eax, 1
    mov ebx, 0
    int 0x80

IMUL (Signed Multiply) – Signed Multiplication

section .data
    signed_num1 db -10
    signed_num2 dw -100
    signed_result dd 0

section .text
    global _start

_start:
    ; 8-bit signed multiplication
    mov al, -5
    mov bl, 4
    imul bl             ; AX = -20

    ; 16-bit signed multiplication
    mov ax, -100
    mov bx, -10
    imul bx             ; DX:AX = 1000

    ; 32-bit signed multiplication
    mov eax, -1000
    mov ebx, 100
    imul ebx            ; EDX:EAX = -100000

    ; Single operand form
    mov eax, 25
    imul eax            ; EDX:EAX = 625

    ; Double operand form
    mov eax, 10
    imul eax, 20        ; EAX = 200

    ; Triple operand form
    imul eax, ebx, 30   ; EAX = EBX * 30

    ; Difference between signed and unsigned multiplication
    mov al, 0xFF        ; Unsigned: 255, Signed: -1
    mov bl, 0xFF        ; Unsigned: 255, Signed: -1

    mul bl              ; AX = 65025 (unsigned)
    ; imul bl           ; AX = 1 (signed: -1 * -1 = 1)

    mov eax, 1
    mov ebx, 0
    int 0x80

4. DIV and IDIV Instructions

DIV (Unsigned Divide) – Unsigned Division

section .data
    dividend16 dw 1000
    divisor8   db 10
    quotient   db 0
    remainder  db 0

section .text
    global _start

_start:
    ; 8-bit division: AX / 8-bit operand = AL(quotient) AH(remainder)
    mov ax, 100
    mov bl, 7
    div bl              ; AL = 14, AH = 2

    mov [quotient], al
    mov [remainder], ah

    ; 16-bit division: DX:AX / 16-bit operand = AX(quotient) DX(remainder)
    mov dx, 0           ; Clear high 16 bits
    mov ax, 10000
    mov bx, 100
    div bx              ; AX = 100, DX = 0

    ; 32-bit division: EDX:EAX / 32-bit operand = EAX(quotient) EDX(remainder)
    mov edx, 0          ; Clear high 32 bits
    mov eax, 1000000
    mov ebx, 1000
    div ebx             ; EAX = 1000, EDX = 0

    ; Large number division example
    mov edx, 1          ; Set high 32 bits
    mov eax, 0          ; Low 32 bits are 0 (total 64 bits: 0x100000000)
    mov ebx, 1000000
    div ebx             ; EAX = 4294, EDX = 967296

    ; Memory operand division
    mov ax, [dividend16]
    mov bl, [divisor8]
    div bl

    mov eax, 1
    mov ebx, 0
    int 0x80

IDIV (Signed Divide) – Signed Division

section .data
    signed_dividend dw -100
    signed_divisor  db 7
    signed_quotient  db 0
    signed_remainder db 0

section .text
    global _start

_start:
    ; 8-bit signed division
    mov ax, -100
    mov bl, 7
    idiv bl             ; AL = -14, AH = -2

    mov [signed_quotient], al
    mov [signed_remainder], ah

    ; 16-bit signed division
    mov dx, -1          ; Set sign extension (for negative numbers)
    mov ax, -10000
    cwd                 ; Sign extend AX to DX:AX
    mov bx, 100
    idiv bx             ; AX = -100, DX = 0

    ; 32-bit signed division
    mov eax, -1000000
    cdq                 ; Sign extend EAX to EDX:EAX
    mov ebx, 1000
    idiv ebx            ; EAX = -1000, EDX = 0

    ; Difference between signed and unsigned division
    mov ax, -100        ; Signed: -100, Unsigned: 65436
    mov bl, 10

    div bl              ; AL = 6, AH = 84 (65436 / 10)
    ; idiv bl           ; AL = -10, AH = 0 (-100 / 10)

    mov eax, 1
    mov ebx, 0
    int 0x80

Complex Arithmetic Operation Examples

Factorial Calculation

section .data
    number dd 5
    factorial dd 0
    result_msg db "Factorial is: ", 0
    msg_len equ $ - result_msg
    newline db 0xA

section .bss
    buffer resb 10

section .text
    global _start

_start:
    ; Calculate factorial: n! = n * (n-1) * ... * 1
    mov eax, [number]
    call calculate_factorial
    mov [factorial], eax

    ; Display result
    mov eax, 4
    mov ebx, 1
    mov ecx, result_msg
    mov edx, msg_len
    int 0x80

    mov eax, [factorial]
    call int_to_ascii
    mov eax, 4
    mov ebx, 1
    mov ecx, buffer
    mov edx, 10
    int 0x80

    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80

; Factorial calculation subroutine
calculate_factorial:
    push ebx
    push ecx

    mov ecx, eax        ; ECX = n
    mov eax, 1          ; EAX = 1 (initial result)

    cmp ecx, 0
    je .done            ; 0! = 1
    cmp ecx, 1
    je .done            ; 1! = 1

.factorial_loop:
    imul eax, ecx       ; EAX = EAX * ECX
    dec ecx
    cmp ecx, 1
    jg .factorial_loop

.done:
    pop ecx
    pop ebx
    ret

; Integer to ASCII subroutine
int_to_ascii:
    mov edi, buffer + 9
    mov byte [edi], 0
    mov ecx, 10

    test eax, eax
    jnz .convert
    mov byte [buffer], '0'
    mov byte [buffer+1], 0
    ret

.convert:
    dec edi
    xor edx, edx
    div ecx
    add dl, '0'
    mov [edi], dl
    test eax, eax
    jnz .convert

    mov esi, edi
    mov edi, buffer
    mov ecx, 10
    rep movsb

    ret

Fibonacci Sequence

section .data
    fib_count dd 10     ; Calculate the first 10 Fibonacci numbers
    fib_msg db "Fibonacci sequence: ", 0
    msg_len equ $ - fib_msg
    space db " ", 0
    newline db 0xA

section .bss
    buffer resb 10

section .text
    global _start

_start:
    ; Display message
    mov eax, 4
    mov ebx, 1
    mov ecx, fib_msg
    mov edx, msg_len
    int 0x80

    ; Calculate and display Fibonacci sequence
    mov ecx, [fib_count]
    mov eax, 0          ; F(0) = 0
    mov ebx, 1          ; F(1) = 1

    call display_number  ; Display F(0)
    call display_space

    dec ecx
    jz .done

    call display_number  ; Display F(1)
    call display_space

    sub ecx, 1
    jz .done

.fib_loop:
    ; F(n) = F(n-1) + F(n-2)
    mov edx, eax
    add edx, ebx        ; EDX = F(n-1) + F(n-2)

    mov eax, ebx        ; EAX = F(n-1)
    mov ebx, edx        ; EBX = F(n)

    push eax
    push ebx
    push ecx

    mov eax, edx
    call display_number
    call display_space

    pop ecx
    pop ebx
    pop eax

    loop .fib_loop

.done:
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80

; Display number subroutine
display_number:
    push eax
    push ebx
    push ecx
    push edx

    call int_to_ascii
    mov eax, 4
    mov ebx, 1
    mov ecx, buffer
    mov edx, 10
    int 0x80

    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

; Display space subroutine
display_space:
    push eax
    push ebx
    push ecx
    push edx

    mov eax, 4
    mov ebx, 1
    mov ecx, space
    mov edx, 1
    int 0x80

    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

; Integer to ASCII subroutine
int_to_ascii:
    mov edi, buffer + 9
    mov byte [edi], 0
    mov ecx, 10

    test eax, eax
    jnz .convert
    mov byte [buffer], '0'
    mov byte [buffer+1], 0
    ret

.convert:
    dec edi
    xor edx, edx
    div ecx
    add dl, '0'
    mov [edi], dl
    test eax, eax
    jnz .convert

    mov esi, edi
    mov edi, buffer
    mov ecx, 10
    rep movsb

    ret

Flags and Conditional Judgments

section .data
    greater_msg db "A is greater than B", 0xA, 0
    less_msg    db "A is less than B", 0xA, 0
    equal_msg   db "A equals B", 0xA, 0
    overflow_msg db "Overflow occurred!", 0xA, 0

section .text
    global _start

_start:
    ; Compare two numbers
    mov eax, 50
    mov ebx, 30

    cmp eax, ebx
    jg .greater
    jl .less
    je .equal

.greater:
    mov ecx, greater_msg
    mov edx, 19
    jmp .display

.less:
    mov ecx, less_msg
    mov edx, 15
    jmp .display

.equal:
    mov ecx, equal_msg
    mov edx, 10

.display:
    mov eax, 4
    mov ebx, 1
    int 0x80

    ; Check for overflow
    mov al, 0x7F        ; 127
    add al, 1           ; 128 (signed overflow)
    jo .overflow        ; Jump if overflow occurs

    ; Unsigned operation check
    mov ax, 0xFF00
    add ax, 0x0100      ; Carry
    jc .carry           ; Jump if carry occurs

    jmp .exit

.overflow:
    mov eax, 4
    mov ebx, 1
    mov ecx, overflow_msg
    mov edx, 18
    int 0x80

.carry:
    ; Carry handling code...

.exit:
    mov eax, 1
    mov ebx, 0
    int 0x80

Summary of Arithmetic Instructions

Key Points:

  1. Basic Operations:

  • INC/DEC – Increment/Decrement
  • ADD/SUB – Addition/Subtraction
  • Multiplication Operations:

    • MUL – Unsigned Multiplication
    • IMUL – Signed Multiplication
    • The result size is double that of the operands
  • Division Operations:

    • DIV – Unsigned Division
    • IDIV – Signed Division
    • The dividend size is double that of the divisor
  • Flag Effects:

    • Overflow Flag (OF)
    • Carry Flag (CF)
    • Zero Flag (ZF)
    • Sign Flag (SF)
  • Best Practices:

    • Pay attention to operand size matching
    • Handle potential overflow situations
    • Use sign extension instructions appropriately (CBW, CWD, CDQ)

    By properly utilizing these arithmetic instructions, a wide range of mathematical computation tasks can be accomplished, from simple to complex.

    Leave a Comment