Assembly
Arithmetic Instructions (ADD/SUB/MUL/DIV)
ADD/SUB
Key insight: ADD/SUB produce the same bit pattern regardless of signed/unsigned interpretation.
asm
; Example: 11111111 + 00000001 = 00000000 (with carry)
; Unsigned: 255 + 1 = 0 (overflow)
; Signed: -1 + 1 = 0 (correct)FLAGS register (EFLAGS)
- CF (Carry Flag): Unsigned overflow
- OF (Overflow Flag): Signed overflow
- ZF (Zero Flag): Result is zero
- SF (Sign Flag): Most significant bit of result
MUL/DIV vs IMUL/IDIV
asm
mul ebx ; Unsigned: result in EDX:EAX (destroys EDX)
imul ebx ; Signed: result in EDX:EAX (destroys EDX)
imul eax, ebx, 3 ; Signed: eax = ebx * 3 (cleaner for simple cases)
div ebx ; Unsigned: EAX = quotient, EDX = remainder
idiv ebx ; Signed: EAX = quotient, EDX = remainder
; Both can crash with divide-by-zero, #DE (divide error) exceptionRemember: div/idiv take the 64-bit EDX:EAX pair as the dividend, not just EAX — so
clear EDX first (e.g. xor edx, edx) or the result is garbage.
asm
mov eax, 100 ; low 32 bits of dividend
xor edx, edx ; clear high 32 bits (so dividend = 100, not garbage)
mov ebx, 7 ; divisor
div ebx ; EAX = 14 (quotient), EDX = 2 (remainder)Why separate MUL/IMUL but not ADD/SUB? ADD/SUB share a bit pattern for signed and unsigned. MUL/DIV need different bit patterns for signed vs unsigned.
Working with memory (including the stack)
Only simple operations work directly on memory:
asm
# Simple operations
add dword [esp+4], 16
sub dword [esp], 5
inc dword [esp+8]
# More complex operations
mov eax, [esp+4] ; Load from memory
imul eax, 3 ; Operate on register
mov [esp+4], eax ; Store back to memorySize specifiers
asm
# When size specifier is REQUIRED
add [esp+4], 16 ; Error: size unknown
add dword [esp+4], 16 ; OK: explicit 32-bit operation
mov [esp], 100 ; Error: size unknown
mov byte [esp], 100 ; OK: explicit 8-bit operation
# When size specifier is NOT needed
add eax, [esp+4] ; OK: eax is 32-bit -> fetch 32 bits
mov [esp+4], eax ; OK: eax is 32-bit -> store 32 bits
mov bl, [esp] ; OK: bl is 8-bit -> fetch 8 bits
add esp, 12 ; OK: esp is 32-bit register
push eax ; OK: push/pop always 32-bit in 32-bit mode