Function:
MOVS moves strings in memory. Possible units to move are byte, word and
doubleword. Typically the source is DS:(E)SI, the target ES:(E)DI
If the single instruction MOVS (not prefixed by REPx) is executed with a
NULL selector in ES or when ES:DI points beyond the segment limit while
executing the the single instruction, causing exception 0dh, the CS:IP
saved by the 0dh exception handler will point after the MOVS instruction,
instead of to it on some 286s.
If a segment limit exception or IOPL violation exception occurs during the
REPx prefixed form of MOVS in Protected Mode, some early 286 will reset CX
to its initial setting (before the REPx started) instead of showing CX as
it was at the time of the exception. SI and DI are not affected and show the
values they had at the time of the exception.
During debugging with breakpoints set, REP MOVS can cause data breakpoints
to be missed on some 386, see <debugging>.
If, on some 386es, MOVS is followed by an instruction which uses a different
address size, or by an instruction which implicitly references the stack
(like POP, PUSH, IRET, RET, CALL, ENTER, LEAVE, PUSHA, POPA, PUSHF and POPF)
while the D-bit for the stack is different from the current address size
used by the MOVS instruction, the destination register updated will depend
on the address size of the instruction that follows, rather than that of
the MOVS. This can result in the updating of only DI when EDI was meant
or EDI when only DI was meant.
The repeated form REPx MOVS has the same bug, but in addition to (E)DI,
also (E)SI is affected.
A workaround is to always code a NOP with the same address size after MOVS
and REPx MOVS.