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:
-
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.