Assembly String Operations — rep movs, stos, scas, and lods
In this tutorial, you will learn about Assembly String Operations. We cover key concepts, practical examples, and best practices to help you master this topic.
Assembly string instructions enable efficient block operations using rep prefixes with movs, stos, lods, and scas for copying, filling, and scanning memory regions.
What You'll Learn
- rep prefix for repeated operations
- movs for block copy
- stos for memory fill
- scas for memory scan
- lods for load string
- Direction flag (DF) control
Why It Matters
String instructions are the fastest way to copy, fill, or search memory. DodaZIP uses rep movs for high-throughput buffer copies in its compression engine. Durga Antivirus Pro uses scas for signature scanning.
Real-World Use
Memory copying (memcpy), buffer filling (memset), string scanning (strlen), and pattern matching in performance-critical library routines.
flowchart LR
A["String Ops"] --> B["rep prefix"]
A --> C["movs"]
A --> D["stos"]
A --> E["scas"]
A --> F["lods"]
B --> G["Repeat RCX times"]
C --> H["Copy"]
D --> I["Fill"]
E --> J["Search"]
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#dbeafe,stroke:#2563eb,color:#1e40af
Direction Flag
cld ; clear DF — forward direction (addresses increase)
std ; set DF — backward direction (addresses decrease)
; Default: cld (forward)
; RSI and RDI are adjusted by the size of the operation
rep movs — Block Copy
; Copy [RSI] to [RDI], RCX bytes/words/dwords/qwords
section .data
src db "Hello, World!", 0
len equ $ - src
section .bss
dst resb 64
section .text
global _start
_start:
cld ; forward direction
mov rsi, src ; source address
mov rdi, dst ; destination address
mov rcx, len ; number of bytes
rep movsb ; copy RCX bytes
; Now dst contains "Hello, World!"
Available sizes: movsb (byte), movsw (word), movsd (dword), movsq (qword).
rep stos — Memory Fill
; Fill [RDI] with value in RAX/EAX/AX/AL, RCX times
section .bss
buffer resb 256
section .text
global _start
_start:
cld
mov rdi, buffer ; destination
mov al, 0 ; fill value
mov rcx, 256 ; count
rep stosb ; fill 256 bytes with 0
; Alternative: fill with pattern
mov rax, 0xDEADBEEF ; qword pattern
mov rdi, buffer
mov rcx, 32 ; 32 qwords = 256 bytes
rep stosq
rep scas — Memory Search
; Scan [RDI] for value in RAX/EAX/AX/AL
; Stops when found or RCX reaches 0
; Sets ZF if found
section .data
msg db "Hello, World!", 0
section .text
global _start
_start:
cld
mov rdi, msg
mov al, ',' ; search for comma
mov rcx, 13
repne scasb ; scan until found or exhausted
; If found: ZF=1, RDI points after match
; If not found: ZF=0, RCX=0
jz found
found:
dec rdi ; RDI was incremented after match
; RDI points to the comma
lods — Load String
; Load value from [RSI] into RAX/EAX/AX/AL, adjust RSI
section .data
msg db "Hello", 0
section .text
global _start
_start:
cld
mov rsi, msg
lodsb ; al = 'H', rsi++
lodsb ; al = 'e', rsi++
lodsb ; al = 'l', rsi++
; AL has each byte sequentially
Implementing strlen
; Returns length of null-terminated string in RAX
strlen:
push rdi
mov rdi, rsi ; string pointer
xor al, al ; search for null
mov rcx, -1 ; maximum count
cld
repne scasb ; scan for null
sub rdi, rsi ; RDI - RSI = bytes scanned
dec rdi ; exclude null terminator
mov rax, rdi
pop rdi
ret
Implementing memcpy
; memcpy(dest in RDI, src in RSI, count in RDX)
memcpy:
push rdi
push rsi
mov rcx, rdx
cld
rep movsb
pop rsi
pop rdi
mov rax, rdi ; return dest
ret
rep Prefix Variants
| Prefix | Condition |
|---|---|
rep |
Repeat while RCX > 0 (for movs/stos) |
repe/repz |
Repeat while RCX > 0 and ZF=1 (for cmps/scas) |
repne/repnz |
Repeat while RCX > 0 and ZF=0 (for scas) |
Common Mistakes
1. Direction flag state
Always set DF with cld or std before string operations. Never assume the state of DF.
2. Wrong operand size
Use movsb for bytes, movsd for dwords, movsq for qwords. Mismatched sizes read/write wrong amounts.
3. Forgetting to initialize RCX
rep uses RCX. If RCX is 0, the operation does nothing. If RCX is huge, it runs forever.
4. Overlapping source and destination
rep movs with overlapping regions and forward direction produces wrong results. Use backward copy (std) for overlapping.
5. Not preserving RSI/RDI
String operations modify RSI and RDI. Save them before calling string routines that use them.
Practice Questions
1. What does rep movsb do?
Copies RCX bytes from address in RSI to address in RDI, incrementing both pointers.
2. How do you fill a buffer with zeros?
cld; mov rdi, buffer; xor eax, eax; mov rcx, size; rep stosb
3. What is the difference between scasb and lodsb?
scasb scans memory comparing with AL (search). lodsb loads a byte from memory into AL (read).
4. What registers do string operations use?
RSI (source), RDI (destination), RCX (count), AL/EAX/RAX (value), DF (direction).
Challenge: Implement memmove that handles overlapping regions correctly.
Solution
memmove:
cmp rsi, rdi
jae .forward
; backward copy for overlapping
mov rcx, rdx
add rsi, rcx
dec rsi
add rdi, rcx
dec rdi
std
rep movsb
cld
ret
.forward:
cld
rep movsb
ret
FAQ
{{< faq question="Are string instructions faster than loops?" >}}
Yes, rep movs can use ERMSB (Enhanced REP MOVSB/STOSB) on modern CPUs, which copies in cache-line-sized chunks for near bandwidth-limit performance.
{{< /faq >}}
{{< faq question="What is ERMSB?" >}} Enhanced REP MOVSB/STOSB is a CPU feature that accelerates rep movsb/stosb for large blocks by using internal microcode optimizations. {{< /faq >}}
{{< faq question="Can string operations be interrupted?" >}} Yes, an interrupt during a rep instruction saves the state of RCX, RSI, RDI. After the interrupt, the instruction resumes where it left off. {{< /faq >}}
{{< faq question="Are string instructions available in 32-bit mode?" >}} Yes, they work in 16-bit, 32-bit, and 64-bit modes. The address size adjusts based on the mode. {{< /faq >}}
{{< faq question="What is the performance of scasb for long strings?" >}} Scasb is slower than a SIMD-based strlen for long strings. Modern implementations use SSE/AVX for scanning. {{< /faq >}}
Mini Project
Write a program that uses string instructions to convert a string to uppercase.
section .data
msg db "hello world", 0
len equ $ - msg
section .text
global _start
_start:
mov rsi, msg
mov rdi, msg
mov rcx, len
cld
.loop:
lodsb
cmp al, 'a'
jb .next
cmp al, 'z'
ja .next
sub al, 32 ; convert to uppercase
.next:
stosb
loop .loop
; Write result
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, len
syscall
mov rax, 60
xor rdi, rdi
syscall
What's Next
Now that you understand string operations, proceed to floating-point arithmetic.
| Topic | Description | Link |
|---|---|---|
| Floating-point | FPU and math | {{< ref "15-floating-point" >}} |
| SSE | SIMD floating-point | {{< ref "16-sse" >}} |
| Instructions | CPU instruction set | {{< ref "06-instructions" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro