String Manipulation Instructions and Comprehensive Applications
If you’ve ever wondered how memcpy can copy 1 GB of data in a fraction of a second, or how strlen can scan a string faster than a simple C loop — the answer often lies in the x86 string manipulation instructions. These are dedicated CPU instructions (MOVSB, STOSB, CMPSB, SCASB, LODSB) that are optimized at the microarchitectural level to operate on memory efficiently.
In this article, we’re going to dissect every string instruction, understand exactly how they work, learn when to use them (and when NOT to), and implement the entire C standard library string functions from scratch. By the end, you’ll be able to write assembly code that rivals — or beats — your C compiler’s output.
Why String Instructions Exist: Operating on Arrays/Memory Blocks Is So Common That CPUs Have Dedicated Instructions
Let’s start with a fundamental observation: a LOT of what computers do is move data around. Copying memory (memcpy), setting memory (memset), comparing memory (memcmp), searching for a character (strchr) — these are some of the most common operations in computing.
The Intel 8086 designers recognized this back in 1978. They added five instructions (LODS, STOS, MOVS, CMPS, SCAS) plus the REP prefix to make these operations fast and compact.
The Problem: Manual Loops Are Slow and Verbose
Without string instructions, copying memory in assembly looks like this:
; Copy RCX bytes from RSI to RDI (manual loop)
copy_loop:
mov al, [rsi]
mov [rdi], al
inc rsi
inc rdi
dec rcx
jnz copy_loop
That’s 7 instructions for a simple copy. Now compare with the string instruction version:
; Copy RCX bytes from RSI to RDI (string instruction)
rep movsb
One instruction! (Well, one instruction plus the REP prefix, but it assembles to just a few bytes.)
The Solution: Microcode Optimizations
But the real magic isn’t just code size — it’s performance. The REP MOVSB instruction is implemented in microcode (firmware inside the CPU) and has been heavily optimized over decades:
- Pentium+:
REP MOVSBchecks for alignment and uses wider transfers (32-bit or 64-bit) internally when possible. - Core 2+:
REP MOVSBis “fast string” optimized — it can copy 16 bytes at a time using internal 128-bit operations. - Ice Lake+:
REP MOVSBcan use EVX-512 to copy 64 bytes at a time!
So REP MOVSB doesn’t actually copy one byte at a time. The CPU dynamically chooses the optimal transfer size based on alignment, size, and CPU capability.
When to Use String Instructions vs SIMD
You might ask: “If REP MOVSB is so fast, why does anyone use SSE/AVX for memcpy?”
Great question. Here’s the tradeoff:
| Scenario | Best Approach | Why |
|---|---|---|
| Small copies (< 128 bytes) | REP MOVSB | Less setup overhead |
| Medium copies (128 bytes – 4KB) | REP MOVSB or unrolled MOVSQ | REP MOVSB is surprisingly fast here |
| Large copies (> 4KB) | SSE2/AVX2 MOVDQU + loop | Can be faster for very large sizes on some CPUs |
| Copy with known alignment | MOVSD/MOVSQ (manual loop) | Avoids alignment checks |
| Variable-sized copy | REP MOVSB | Handles everything in one instruction |
Rule of thumb: For general-purpose memcpy, REP MOVSB is a solid choice. For performance-critical code where you know the sizes in advance, hand-optimized SSE2/AVX2 can be faster.



