CLD clears the direction flag (DF = 0); STD sets it (DF = 1). DF affects only the string instructions: it decides whether SI and DI go up or down after each element. Nothing else changes.

DFSet byBytesWordsStart SI / DI at
0CLD+1+2the first element
1STD-1-2the last element

Put CLD before string code unless you are certain of DF. DOS does not promise its value, and an interrupt handler that uses string instructions must set it too, since it can interrupt code running with DF = 1. Code that uses STD should put CLD back when done, because almost all other code assumes forward. PUSHF / POPF save and restore it with the other flags.

Overlapping copies

Copy a block to a higher address that overlaps it and a forward copy overwrites source bytes before it reads them. Copy backward instead: point SI and DI at the last element of each block (for words, the last word: start + length - 2), STD, then REP MOVSB. When the destination is lower than the source, forward is the safe way. The example moves "ABCDE" one place to the right inside the same buffer.

STD ; backward
MOV SI, OFFSET TXT1 + 4 ; the "E"
MOV DI, OFFSET TXT1 + 5 ; one place to the right
MOV CX, 5
REP MOVSB
CLD ; forward again
MOV DX, OFFSET TXT1
MOV AH, 09h ; DOS: print the string at DS:DX
INT 21h
TXT1 DB 'ABCDE ', 13, 10, '$'

It prints AABCDE. Done forward (SI = TXT1, DI = TXT1 + 1, CLD) it would print AAAAAA: each byte copied becomes the source of the next. That effect is sometimes used on purpose to fill a block with a repeating pattern.