Floating-Point Operations and SIMD Instructions
Floating-Point Instruction Set (FPU)
FPU Register Stack Structure:
- 8 floating-point registers of 80 bits each:
ST(0)–ST(7) - Operated as a stack (push/pop)
- Independent status register (
FSW) and control register (FCW)
Core Instructions:
; Load floating-point number into ST(0)
fld dword [mem32] ; Load 32-bit float from memory
fld qword [mem64] ; Load 64-bit float from memory
; Floating-point addition
fadd st0, st1 ; ST(0) = ST(0) + ST(1)
faddp st1, st0 ; ST(1) = ST(1) + ST(0), then pop ST(0)
; Floating-point multiplication
fmul st0, st1 ; ST(0) = ST(0) * ST(1)
; Floating-point comparison
fcom st1 ; Compare ST(0) and ST(1)
fstsw ax ; Store FPU status word into AX
sahf ; Transfer to CPU flags register
Modern Alternatives:
- x87 FPU is gradually being replaced by SIMD instructions
- Still used when high-precision computation is required
SIMD Instruction Set Evolution
| Instruction Set | Release Year | Register Width | Key Features |
|---|---|---|---|
| MMX | 1996 | 64-bit | 64-bit integer parallel operations |
| SSE | 1999 | 128-bit | Single-precision floating-point |
| SSE2 | 2001 | 128-bit | Double-precision floating-point + integers |
| AVX | 2011 | 256-bit | Three-operand encoding |
| AVX-512 | 2013 | 512-bit | Mask registers |
SSE Instruction Examples
; Load 128-bit data
movaps xmm0, [mem128] ; Aligned load
movups xmm1, [mem128] ; Unaligned load
; Floating-point addition (four single-precision floats in parallel)
addps xmm0, xmm1
; Data conversion
cvtps2dq xmm2, xmm0 ; Convert single-precision floats to 32-bit integers
AVX Instruction Enhancements
; Three-operand syntax
vaddps xmm0, xmm1, xmm2 ; xmm0 = xmm1 + xmm2 (xmm1/xmm2 unchanged)
; Broadcast load
vbroadcastss xmm3, dword [mem32] ; Broadcast 32-bit value to all four elements of xmm3
; Masked operation
vmulps xmm4, xmm5, xmm6, {k1} ; Use mask k1 to control operation
Data Transfer and Address Calculation
MOV Instruction Variants
; Register-to-register transfers
movb %al, %bl ; 8-bit
movw %ax, %bx ; 16-bit
movl %eax, %ebx ; 32-bit
movq %rax, %rbx ; 64-bit
; Memory transfers
movb [mem8], %al ; Byte store
movdqu (%rdi), %xmm0 ; 128-bit unaligned load
XCHG Instruction Characteristics
xchg %eax, %ebx ; Swap two registers
xchg %ax, [mem16] ; Swap register and memory
; Atomic exchange with implicit LOCK prefix
lock xchg %eax, [mem32]
LEA Instruction Tricks
lea eax, [ebx+ecx*4] ; Compute ebx + ecx*4 → eax
lea edx, [rip+0x1234] ; RIP-relative addressing (64-bit mode)
lea rsi, [rax*8+rbx] ; Complex address calculation
Stack Operation Optimization
Advanced PUSH/POP Usage
; Save multiple registers
push %rax
push %rbx
push %rcx
; Fast argument passing
push $42 ; Push immediate
pushq %rdi ; Push register
; Stack space allocation
sub $0x20, %rsp ; Allocate 32 bytes of stack space
... ; Use stack space
add $0x20, %rsp ; Deallocate stack space
Conditional Execution and Bit Manipulation
CMOVcc – Conditional Move
cmovz %eax, %ebx ; If ZF=1, then EBX = EAX
cmovg %ecx, %edx ; If SF=OF and ZF=0, then EDX = ECX
; Typical use: avoid branch misprediction
mov %eax, %edx
sub %ebx, %edx
cmovl %ecx, %eax ; If result < 0, then EAX = ECX
SETcc – Conditional Set
sete %al ; If ZF=1, then AL = 1
setne %bl ; If ZF=0, then BL = 1
setg %cl ; If SF=OF and ZF=0, then CL = 1
Bit Test and Modify Instructions
bt $3, %ebx ; Test bit 3 of EBX, set CF
bts $5, %ecx ; Set bit 5 of ECX, set CF
btr $2, %edx ; Clear bit 2 of EDX, set CF
btc $4, %esi ; Toggle bit 4 of ESI, set CF
Bit Scan Instructions
bsf %eax, %ebx ; Find position of least significant 1-bit in EBX → EAX
bsr %ecx, %edx ; Find position of most significant 1-bit in EDX → ECX
Atomic Operations and Synchronization
LOCK Prefix Usage
lock addl $1, (%rdi) ; Atomic increment
lock xchgl %eax, (%rsi) ; Atomic exchange
lock cmpxchg %ecx, (%rdx) ; Atomic compare-and-swap
CMPXCHG Instruction
; Basic form
cmpxchg %eax, (%rdi) ; If AL == [EDI], then [EDI] = EAX, ZF = 1
; Extended form (64-bit)
cmpxchgq %rax, (%rdi) ; 64-bit compare-and-swap
; Implement spinlock
spin_lock:
mov $1, %rax
1: xchg %rax, (%rdi)
test %rax, %rax
jnz 1b
Control Transfer Instructions
Jump Instructions Explained
Unconditional Jumps:
jmp label ; Direct jump
jmp *%rax ; Indirect jump (via register)
jmp *(%rdi) ; Indirect jump (via memory)
Conditional Jump Combinations:
; Multi-condition example
cmp %eax, %ebx
jae label1 ; Unsigned >=
jb label2 ; Unsigned <
jg label3 ; Signed >
jl label4 ; Signed <
Subroutine Calling Conventions
cdecl Example:
; Caller
push %ecx ; Push argument
push %edx
call my_func
add $8, %rsp ; Clean up stack
; Callee
my_func:
push %rbp
mov %rsp, %rbp
sub $16, %rsp ; Local variable space
... ; Function body
leave
ret
64-bit System V Calling Convention:
; Arguments passed via registers
mov %rdi, %rax ; First argument → RAX
mov %rsi, %rcx ; Second argument → RCX
call target_func
; Return value in RAX
Instruction Set Evolution and Optimization
AVX-512 Enhanced Features
- 512-bit vector operations
- Mask registers (
k0–k7) - Broadcast/shuffle instructions
- Alignment checking
Examples:
; Masked load
vmovdqa64 zmm0{k1}, [mem64] ; Load using mask k1
; Fused multiply-add
vfmadd231ps zmm1, zmm2, zmm3 ; zmm1 = zmm2*zmm3 + zmm1
Performance Optimization Techniques
Instruction Scheduling Example:
Original code:
mov %rax, (%rdi)
add $1, %rbx
mov (%rsi), %rcx
Optimized (eliminate data dependencies):
mov (%rsi), %rcx ; Independent instruction moved forward
mov %rax, (%rdi) ; Memory operation
add $1, %rbx ; Simple arithmetic
Branch Prediction Hints:
// Hint: branch likely taken
likely_branch:
cmovnz %rax, %rbx
__builtin_expect(1, 1); // GCC intrinsic
// Hint: branch unlikely taken
unlikely_error:
__builtin_expect(error_code, 0);
By deeply understanding these instruction set features and optimization techniques, developers can:
- Write high-performance numerical computation code
- Implement low-latency system programming
- Develop safety-critical applications
- Perform low-level system optimization
- Design efficient algorithm implementations



