x86 groups a large, irregular instruction set behind common data movement, arithmetic, bit manipulation, control-flow, and string-processing patterns. Operand size, address size, execution mode, prefixes, and ISA extensions can change an instruction’s encoding or availability. Intel’s and AMD’s architecture manuals remain authoritative; successful assembly only proves that a tool can encode the source.
Data Movement and Address Generation #
MOV copies an immediate or register value to a register or memory, or copies
memory to a register. An ordinary MOV has at most one explicit memory operand.
MOVZX zero-extends a narrower integer, while MOVSX and MOVSXD sign-extend.
A 32-bit general-purpose-register destination in 64-bit mode implicitly clears
the upper 32 bits.
CMOVcc conditionally copies a register or memory source according to status
flags without changing control flow. A memory-source conditional move can still
perform the source read before selecting the result, so it must not be used to
guard an invalid address. SETcc writes a byte result from the same condition
families.
XCHG exchanges two operands. Its memory form has locked semantics even without
an explicit LOCK prefix, making it atomic with respect to other processors for
the addressed memory. Atomicity does not make a compound algorithm correct;
ordering, cache-line placement, and retry behavior still matter.
LEA calculates an effective address and writes the arithmetic result without
accessing memory:
lea rax, [rdi + rdi*4] ; rax = rdi * 5Compilers use LEA for pointer calculation and selected additions or constant
multiplications. Segment bases and paging are not applied because no memory
operand is dereferenced.
Stack Operations #
PUSH decrements the stack pointer and stores a value; POP loads a value and
increments it. Exact operand-size behavior depends on mode. The platform ABI,
not the instruction, determines alignment, red zones, shadow space, saved
registers, and which memory is valid stack storage.
CALL stores a return address and transfers control, while a near RET loads
the return address from the stack. A mismatched stack pointer or corrupted
return address therefore changes control flow. Far calls, far returns, call
gates, and IRET additionally process segment or privilege state and should not
be treated as ordinary function-call instructions.
Integer Arithmetic, Comparison, and Flags #
ADD, ADC, SUB, and SBB implement ordinary and multi-precision
arithmetic. ADC consumes carry flag CF, and SBB consumes it as a borrow, so
low-to-high limb sequences propagate carry or borrow. INC and DEC update
several arithmetic flags but preserve CF.
CMP performs a subtraction only to set flags. TEST performs a bitwise AND
only to set flags. Conditional branches, moves, and byte-setting instructions
then interpret those flags:
- Equality uses
ZF. - Unsigned ordering uses
CFandZF. - Signed ordering combines
SF,OF, andZF.
CF records unsigned carry or borrow, while OF records signed overflow. The
same bit pattern therefore requires a signed or unsigned condition matching the
program’s data interpretation.
Single-operand MUL and IMUL multiply an accumulator by an explicit operand
and produce a double-width result in implicit high and low registers. Two- and
three-operand IMUL forms write a truncated result to an explicit destination.
DIV and IDIV divide a double-width implicit dividend. They raise divide error
for a zero divisor or a quotient that cannot fit the destination; software must
prepare the high half correctly before division.
Logical, Bit-Test, Shift, and Rotate Operations #
AND, OR, XOR, and NOT operate bitwise. Clearing a register with
xor eax, eax is a common dependency-breaking idiom on current out-of-order
processors, but its architectural result is simply zero.
BT copies a selected bit to CF; BTS, BTR, and BTC also set, reset, or
complement the bit. A memory bit index can address beyond the encoded memory
operand, which makes bounds reasoning important. An explicit LOCK prefix can
make supported read-modify-write memory forms atomic.
BSF and BSR locate the least- or most-significant set bit. Their destination
is undefined for a zero source. TZCNT and LZCNT provide defined zero-input
results when the relevant extension is present, but their encodings can execute
as BSF or BSR on processors without that extension. Feature detection is
therefore required.
SHL and SAL are equivalent left shifts. SHR shifts in zero bits, while
SAR replicates the sign bit. ROL and ROR rotate within the operand; RCL
and RCR rotate through CF. Shift counts are masked according to operand size,
and flag results for large or zero counts require consulting the instruction
definition.
Direct and Indirect Control Flow #
Near JMP, CALL, and conditional Jcc instructions can use relative
displacements measured from the end of the instruction. Indirect JMP and
CALL read the destination from a register or memory. RET obtains its
destination from the stack. Indirect targets interact with control-flow
integrity, return prediction, and speculation mitigations, so equivalent-looking
forms can have different security or performance properties.
Short conditional branches encode an 8-bit signed displacement. Near forms use a wider displacement in 32- and 64-bit modes. x86 has no general instruction that conditionally calls or returns; code composes those operations with a conditional branch.
Exceptions, software interrupts, and external interrupts transfer through the
interrupt descriptor table. INT, IRET, and gate-based transfers have
privilege semantics beyond ordinary branches. SYSCALL/SYSRET and
SYSENTER/SYSEXIT use model-specific configuration and an operating-system
ABI.
String Instructions and Repeat Prefixes #
MOVS, CMPS, SCAS, LODS, and STOS use implicit source, destination,
accumulator, and count registers. Byte, word, doubleword, and selected quadword
forms make element size explicit. The direction flag (DF) chooses whether
index registers increment or decrement.
REP repeats an operation while the count is nonzero. REPE/REPZ and
REPNE/REPNZ additionally use ZF with comparison or scan instructions.
Current processors can optimize large REP MOVSB and REP STOSB operations,
but feature and size-dependent library dispatch remains an implementation
decision.
Forward rep movsb is unsafe when the destination starts inside and above the
source range because early stores overwrite bytes that have not been read.
Backward copying can handle that overlap:
std ; decrement indexes
rep movsb
cld ; restore the ABI-required directionThe caller must initialize pointers to the final elements for a backward copy.
Most x86 ABIs require DF=0 on function entry and return, so code that executes
STD must restore it even on failure paths. Production memmove
implementations also choose direction and optimized sequences according to
overlap, size, and processor features.
Privileged operations such as CLI, STI, LGDT, LIDT, control-register
access, port I/O, and HLT are constrained by current mode and privilege.
Assembler acceptance does not grant execution permission.
Comments
Read or comment on GitHub (sign-in required to comment)