Assembly Language - Logical Instructions
Logical instructions are used for bit-level operations in assembly programming, widely used for masking operations, bit extraction, flag setting, and efficient multiplication/division.
AND - Bitwise AND
AND performs a bitwise "AND" operation on two operands (result is 1 only when both are 1).
Example
; File path: and_demo.asm
; AND instruction example
section.text
global _start
_start:
; Basic bitwise AND
mov eax,0x0F0F; 0000 1111 0000 1111
and eax,0x00FF; 0000 0000 1111 1111
; Result: eax = 0x000F ; 0000 0000 0000 1111
; Common trick 1: Mask lower 4 bits (keep lower 4 bits)
mov eax,0xAB; 1010 1011
and eax,0x0F; 0000 1111
; eax = 0x0B ; 0000 1011
; Common trick 2: Check parity (AND with 1)
mov eax,42; even number
and eax,1; eax = 0 (even)
; The last bit of 42 in binary is 0, 42 & 1 = 0
mov eax,43; odd number
and eax,1; eax = 1 (odd)
; The last bit of 43 in binary is 1, 43 & 1 = 1
; Common trick 3: Clear register to zero
xor eax,eax; Equivalent to mov eax, 0, but faster and shorter
; AND sets flags: CF=0, OF=0, ZF and SF based on result
mov eax,1
mov ebx,0
int 0x80
OR - Bitwise OR
OR performs a bitwise "OR" operation on two operands (result is 1 if at least one is 1).
Example
; OR instruction example
; Combine flag bits
mov eax,0x0F00; 0000 1111 0000 0000
or eax,0x00FF; 0000 0000 1111 1111
; eax = 0x0FFF ; 0000 1111 1111 1111
; Set a specific bit (set bit 3 to 1)
mov eax,0; 0000 0000
or eax,0x08; 0000 1000
; eax = 0x8 ; 0000 1000
; Case conversion: uppercase to lowercase
mov al,'A'; al = 0x41 (0100 0001)
or al,0x20; 0x20 = 0010 0000
; al = 0x61 = 'a' ; 0110 0001
NOT - Bitwise NOT
NOT inverts each bit of the operand (0 becomes 1, 1 becomes 0).
Example
; NOT instruction example
mov eax,0x0F0F0F0F; 0000 1111 0000 1111 ...
not eax; 1111 0000 1111 0000 ...
; eax = 0xF0F0F0F0
; NOT does not affect any flags (unlike AND/OR/XOR)
XOR - Bitwise XOR
XOR performs a bitwise "exclusive OR" operation on two operands (result is 1 when different, 0 when same).
Example
; File path: xor_demo.asm
; XOR instruction example
section.text
global _start
_start:
; Basic XOR
mov eax,0x0F0F; 0000 1111 0000 1111
xor eax,0x00FF; 0000 0000 1111 1111
; Result: eax = 0x0FF0 ; 0000 1111 1111 0000
; Classic trick 1: Clear register to zero (more efficient than mov reg, 0)
xor eax,eax; eax = 0, only takes 2 bytes
xor ebx,ebx
xor ecx,ecx
; Classic trick 2: Swap two registers (no third temporary register needed)
mov eax,100; eax = 100
mov ebx,200; ebx = 200
xor eax,ebx; eax = 100 xor 200
xor ebx,eax; ebx = 200 xor (100 xor 200) = 100
xor eax,ebx; eax = (100 xor 200) xor 100 = 200
; Now eax = 200, ebx = 100 (swap complete!)
; Classic trick 3: Simple encryption/decryption
mov al,'A'; Original character 'A' = 0x41
xor al,0x55; Encrypt: al = 'A' xor 0x55
; al is now some garbled value
xor al,0x55; Decrypt: xor with 0x55 again to restore
; al = 'A' is back!
mov eax,1
mov ebx,0
int 0x80
The XOR swap trick is cool, but on modern CPUs it's less efficient than using the
XCHGinstruction or a temporary register. Know it, but don't obsess over using it.
Shift Instructions
Shift instructions move binary bits left or right, commonly used for efficient multiplication/division (multiply by 2, divide by 2, etc.).
| Instruction | Function | Example |
|---|---|---|
| SHL | Logical shift left (left bits out, right padded with 0) | shl eax, 1 (multiply by 2) |
| SHR | Logical shift right (right bits out, left padded with 0) | shr eax, 1 (unsigned divide by 2) |
| SAL | Arithmetic shift left (same as SHL) | sal eax, 1 |
| SAR | Arithmetic shift right (right bits out, left preserves sign bit) | sar eax, 1 (signed divide by 2) |
Example
; File path: shift_demo.asm
; Shift instruction example
section.text
global _start
_start:
; SHL: Logical shift left = multiply by power of 2
mov eax,10; eax = 10 (1010)
shl eax,1; eax = 20 (10100), i.e. 10Γ2
shl eax,2; eax = 80 (1010000), i.e. 20Γ4
; SHR: Logical shift right = unsigned divide by power of 2
mov eax,80; eax = 80
shr eax,3; eax = 10, i.e. 80Γ·8
; SAR: Arithmetic shift right = signed divide by power of 2 (preserves sign bit)
mov eax,-16; eax = -16 (0xFFFFFFF0)
sar eax,2; eax = -4 (0xFFFFFFFC), i.e. -16Γ·4
; SAR vs SHR:
; If eax = 0xFFFFFFF0 (-16), SHR would give 0x3FFFFFFC (very large positive number)
; While SAR gives 0xFFFFFFFC (-4), preserving the sign bit
; The last bit shifted out goes into CF flag
mov eax,5; 0101
shr eax,1; eax = 2, CF = 1 (the trailing 1 was shifted out)
jc carry_was_set ; If CF=1, the original number was odd
carry_was_set:
mov eax,1
mov ebx,0
int 0x80
Rotate Instructions
Rotate instructions move shifted-out bits back to the other end, forming a loop:
| Instruction | Function |
|---|---|
| ROL | Rotate left (bypassing CF) |
| ROR | Rotate right (bypassing CF) |
| RCL | Rotate left through carry (through CF) |
| RCR | Rotate right through carry (through CF) |
Example
; Rotate instruction example
; ROL: Rotate left
mov al,0x85; 1000 0101
rol al,1; Shift left by 1: 0000 1011
; CF = 1 (highest bit shifted out to CF)
; Meanwhile the original CF of 1 is shifted into lowest bit, forming a loop
; ROL actual effect: shift left by 1, highest bit goes to both CF and lowest bit
; 1000 0101 -> ROL 1 -> 0000 1011
; RCL: Rotate left through carry (CF participates in rotation)
clc; Clear CF = 0
mov al,0x85; 1000 0101
rcl al,1; CF participates: CF bit7...bit0 -> CF
; Result: 0000 1010, CF = 1
; Rotate instructions are commonly used in encryption algorithms and bit operations
Practical Uses of Logical Operations
A comprehensive exampleβusing logical operations to implement a simple bit flag system:
Example
; File path: bit_flags.asm
; Using logical operations to implement a bit flag system
section.data
flags db 0; 8 flag bits, all initially 0
; bit0: is active
; bit1: is visible
; bit2: needs save
; bit3: is modified
FLAG_ACTIVE equ 1; 0000 0001
FLAG_VISIBLE equ 2; 0000 0010
FLAG_NEED_SAVE equ 4; 0000 0100
FLAG_MODIFIED equ 8; 0000 1000
section.text
global _start
_start:
; Set flag bits: OR
mov al,
or al, FLAG_ACTIVE ; Set bit0
or al, FLAG_VISIBLE ; Set bit1
; al = 0000 0011 = 3
mov,al
; Check flag bits: AND + TEST
test byte, FLAG_ACTIVE ; Test if bit0 is 1
jnz is_active ; ZF=0 means the bit is 1
is_active:
; Clear flag bits: AND + NOT
mov al,
and al, ~FLAG_VISIBLE ; Clear bit1 (preserve other bits)
; al = 0000 0001 = 1
mov,al
; Toggle flag bits: XOR
mov al,
xor al, FLAG_MODIFIED ; Toggle bit3
; If it was 0 becomes 1, if it was 1 becomes 0
mov eax,1
mov ebx,0
int 0x80
Bit flag operations are extremely common in systems programming. Operating system kernels, device drivers, and embedded systems widely use this technique to manage state.
YouTip