Last modified: Thu Jun 18 07:11:46 UTC+0200 2026 © A. Tarpai
x86 String Instructions and REP
8086 String Instructions and REP
For fast memcopy and memfill (MOVS, STOS) of bytes or words.
Compare strings (CMPS), scan string (SCAS) f. ex. to find trailing zero, fast strlen.
One-byte opcodes:
+----------+-+ +----------+-+ | |z| | |w| +----------+-+ +----------+-+ REP PREFIX MOVS CMPS STOS LODS SCAS F2 z=0 REPNE/REPNZ w = 0 BYTE F3 z=1 REP/REPE/REPZ w = 1 WORD
Implicit use of SI, DI pointers with default SEGREG:
(DS):SI --> ES:DI
- DI points to destination operand in the segment indicated by ES; no segment override is possible.
- SI points to source operand, default DS segment override is possible.
SI/DI automatically incremented or decremented by operand size of 1 or 2 after the operation (post-inc/dec). The only instructions on Intel with this addressing behaviour. Based on DF flag, 0 means increment (CLD/STD).
REP: ZF and 'z' has only meaning for CMPS and SCAS. Mnemonics are such that it is for repeat, i.e. REPNE repeats when comparison is not equal (repeats when ZF=0).
Operation:
prev instr prev instr prev instr
| | |
| OP REP OP REPz
| | CX=0 | CX=0
| +---------> TEST CX ------>----+ +---------> TEST CX ------>----+
| | |* | | |* |
| | DEC CX | | DEC CX |
| | | | | | |
OP STR | OP STR | | OP STR |
| | | | | | |
adjust | adjust | | adjust |
SI/DI | SI/DI | | SI/DI |
| | | | | z==ZF | |
| +------<------+ | +------<--- TEST ZF |
| | | |
next instr next instr <----------+ next instr <----------+
MOVS [DI,SI] REP MOVS [DI,SI] REPz CMPS [SI,DI]
STOS [DI] REP STOS [DI] REPz SCAS [AX,DI]
LODS [SI] REP LODS [SI]
CMPS [SI,DI]
SCAS [AX,DI]
Showing instructions with unnecessary implicit operands
* Interrupts served here
A repeating string operation can be suspended by an exception or interrupt.
MOVS: move from source to destination.
LODS (Load string): Loads (DS):SI --> ACCU. With REP a little meaningless, but gets last value.
STOS (Store string): moves content of ACCU --> ES:DI
CMPS (Compare Strings): subtracts the destination(!) string element at ES:DI
from the source string element (DS):SI and updates the flags AF, SF, ZF, PF, CF and OF.
SCAS (Scan String): subtracts the destination(!) string element at ES:DI
from AX/AL and updates the flags AF, SF, ZF, PF, CF and OF.
Repeated CMPS and SCAS instructions can be exited if the count is exhausted or if the zero flag fails the repeat condition. Tests CX or ZF for termination condition. That is find a value (ZF=1) and maximize compare length (CX).
Note: when the flag fails and REPz exits - SI/DI already adjusted to next item. Eg. find trailing zero with SCAS:
OR CX, -1 <-- set CX to max
MOV AL, 0
REPNE SCASB <-- repeat for not equal
h e l l o \0 .
^ ^
| |
DI DI points
to byte following \0
NOT CX <-- CX=-7 --> CX=6: can be used to strcpy including trailing zero
set si/di..
REP MOVSB
386 String Instructions and REP
Both address- (67) and operand size (66) matters. Orthogonal extension, eg. we can memcopy anywhere using 16-bit RM code (after limit extend) by using 66/67.
rep movs (w=1) with NASM examples:
| [BITS 16] | [BITS 32] | operand-size | address-size | ||||
|---|---|---|---|---|---|---|---|
| opcode | syntax | opcode | syntax | Move | Adjust Register by | Address Register | REP test and decrement |
| F3 A5 | REP MOVSW | 67 66 F3 A5 | a16 rep movsw | WORD | 2 | SI/DI | CX |
| 66 F3 A5 | REP MOVSD | 67 F3 A5 | a16 rep movsd | DWORD | 4 | SI/DI | CX |
| 67 F3 A5 | A32 REP MOVSW | 66 F3 A5 | rep movsw | WORD | 2 | ESI/EDI | ECX |
| 67 66 F3 A5 | A32 REP MOVSD | F3 A5 | rep movsd | DWORD | 4 | ESI/EDI | ECX |
66 operand-size attribute:
- move 16 or 32-bits
- inc/dec (E)SI/(E)DI by 2 or 4
67 address-size attribute:
- use SI/DI or ESI/EDI for operand address
- decrement CX or ECX for REP
Operation:
address-size = 32 address-size = 16
D=1 or D=0 and 67h D=0 or D=1 and 67h
REP
+-------------------+ +---------+---------+
| | ECX | . . . . | CX | ECX
+-------------------+ +---------+---------+
Test ECX Test CX
Decrement ECX Decrement CX
ECX HI unchanged (.)
STRING OP
+-------------------+ +---------+---------+
| | ESI/EDI | . . . . | SI/DI | ESI/EDI
+-------------------+ +---------+---------+
| |
v v
+-------------------+ +---------+---------+
| | | 0 0 0 0 | |
+-------------------+ +---------+---------+
+-------------------+ +-------------------+
| SR:BASE | | SR:BASE |
+ +-------------------+ +-------------------+
________________________________________________________________
+-------------------+ +-------------------+
| EFFECTIVE ADDRESS | | EFFECTIVE ADDRESS |
+-------------------+ +-------------------+
ADJUST
+-------------------+ +---------+---------+
| | ESI/EDI | . . . . | SI/DI | ESI/EDI
+-------------------+ +---------+---------+
Inc/Dec ESI/EDI Inc/Dec SI/DI
SI/DI HI unchanged (.)
Note that REP is also a prefix - not an instruction. So CX/SI/DI or ECX/ESI/EDI are affected together by address-size.
186/286 INS/OUTS
186/286 added INS/OUTS string I/O and can be used with REP: pumping bytes or words through an I/O port and continuous memory area pointed by SI/DI.
One-byte opcodes, variable port in DX only. Thus every operand is implicit:
0 1 1 0 1 1 0 W INS [ES:DI], [DX=PORT] 0 1 1 0 1 1 1 W OUTS [DX=PORT], [DS:SI]
Same operation as string instructions:
- SI/DI register is incremented or decremented automatically according to the setting of the DF flag in the EFLAGS register
- REP prefix for block input/output of CX bytes or words.
Assembler syntax:
6C/6D [REP] INSB/INSW 6E/6F [REP] OUTSB/OUTSW
The only thing changeable is segment-override for DS:SI (then full syntax is accepted).
386 INS/OUTS
Honors both operand- and address-size (similar to other string instructions).
Operand-size determines port width, similar to IN/OUT:
[rep] insb/outsb 8-bit I/O port W=0 [rep] insw/outsw 16-bit I/O port W=1 D=0 or D=1 and 66h [rep] insd/outsd 32-bit I/O port W=1 D=1 or D=0 and 66h
Address-size attribute determines DI/EDI (and CX/ECX for REP) similar to string instructions.
Assembler syntax
VC++. Eg. writing ins defaults to ins byte ptr es:[edi],dx:
ins 6C ins byte ptr es:[edi],dx insb 6C ins byte ptr es:[edi],dx insw 66 6D ins word ptr es:[edi],dx insd 6D ins dword ptr es:[edi],dx