Strings in Assembly
Assembly has no native string type; a string is simply a sequence of bytes in memory, and its length must be tracked by convention. The two dominant conventions are null-terminated strings, where a single 0x00 byte marks the end (as in C and most x86 system code), and length-prefixed strings, where a count precedes the data. Every string operation — copying, comparing, finding a character — must respect whichever convention the code was written for, since mixing them silently misreads memory.
Cricket analogy: A cricket over is conventionally over the moment six legal balls are bowled, with no separate counter object — the umpire just watches for the sixth ball, the way null-terminated code watches for the terminating zero byte.
Computing String Length and Copying
A classic strlen implementation scans forward from the string's start, incrementing a counter until it reads a zero byte, then returns the counter; this is an O(n) scan performed every single time the length is needed, since the length is never cached. Copying a string similarly walks both source and destination pointers in lockstep, copying one byte at a time and stopping only after the null terminator itself has been copied, so the destination buffer must be at least as large as the source including that terminator.
Cricket analogy: Working out a batting partnership's total by adding each ball-by-ball run one at a time, rather than reading a pre-summed total, mirrors strlen's byte-by-byte scan instead of a cached length field.
section .data
msg: db "Hello, Assembly!", 0 ; null-terminated string
section .text
global _start
strlen: ; rdi = pointer to string, returns length in rax
xor rax, rax
.next:
cmp byte [rdi + rax], 0
je .done
inc rax
jmp .next
.done:
ret
_start:
mov rdi, msg
call strlen ; rax now holds 16
mov eax, 60
xor edi, edi
syscall
Comparing and Searching Strings
String comparison walks two buffers together, comparing corresponding bytes until either a mismatch is found or both strings hit their null terminator simultaneously, at which point they're equal. x86 provides the CMPSB instruction paired with the REPE prefix specifically for this: REPE CMPSB repeats byte comparison while ZF is set and RCX is nonzero, stopping the instant a mismatch occurs, which is exactly how a hand-rolled strcmp loop behaves but expressed as a single repeated instruction.
Cricket analogy: Comparing two teams' over-by-over scoring rates ball by ball until the first over where they diverge is exactly how REPE CMPSB compares bytes until the first mismatch halts the repeat.
REPE CMPSB (and SCASB, MOVSB used this way) reads or writes memory through RSI/RDI without any bounds checking. If two buffers being compared are not actually null-terminated as expected, the instruction will keep scanning past the intended buffer into unrelated memory until it happens to find a matching or mismatching byte — a classic source of buffer over-reads.
- Assembly strings are raw byte sequences; the language enforces no type, so the ending convention (null-terminated or length-prefixed) must be tracked by the programmer.
- Null-terminated strings end with a single 0x00 byte; length must be discovered by scanning, as with a hand-written or REPNE SCASB-based strlen.
- strlen-style scans are O(n) and are not cached, so repeated length queries re-scan the whole string each time.
- Copying a null-terminated string must include the terminator itself, and the destination buffer must be large enough to hold source length + 1.
- REPE CMPSB compares bytes while ZF is set and RCX is nonzero, halting at the first mismatch, mirroring a hand-written comparison loop.
- String instructions like CMPSB, SCASB, and MOVSB perform no bounds checking, so mismatched buffer sizes or missing terminators cause reads past the intended memory.
Practice what you learned
1. What marks the end of a null-terminated string?
2. Why is a hand-written strlen loop described as O(n) and uncached?
3. What does the REPE prefix do when combined with CMPSB?
4. When copying a null-terminated string, what must the destination buffer accommodate?
5. What is the main risk of using CMPSB/SCASB on a buffer that isn't properly terminated?
Was this page helpful?
You May Also Like
Arrays in Assembly
How fixed-size, contiguous arrays are declared, laid out in memory, and indexed using scaled addressing in x86-64 assembly.
Pointers and Indirection
How addresses, dereferencing, pointer arithmetic, LEA, and multiple levels of indirection work at the machine level in x86-64 assembly.
The Heap and Dynamic Memory
How assembly programs request and manage runtime memory using brk/sbrk and mmap, and the manual bookkeeping needed to avoid leaks.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics