why do repe and repne do the same before movsb?

In the machine code, there are actually only two different prefix bytes.

  • 0xF3 is called REP when used with MOVS/LODS/STOS/INS/OUTS (instructions which don't affect flags)
  • 0xF3 is called REPE or REPZ when used with CMPS/SCAS
  • 0xF2 is called REPNE or REPNZ when used with CMPS/SCAS, and is not documented for other instructions.

Intel's insn reference manual REP entry only documents F3 REP for MOVS, not the F2 prefix. Congratulations, you've found an undocumented encoding for REP MOVSB, at least on whatever CPU you tested this on. :)

See also this appendix of the NASM manual which includes other undocumented opcodes, but not this F2 A4 REPNE MOVSB. (linked from the x86 tag wiki).


Normally, prefixes which don't affect an instruction are ignored, so I would have expected REPNE MOVSB to run identically to just MOVSB. e.g. TZCNT is encoded as REP BSF, and on CPUs which don't support BMI1, it simple executes as BSF. (Doing the same thing except when the source is zero.)

Similarly, REP RET is a common trick to introduce padding to work around a limitation of AMD K8/K10 branch predictors, and runs the same as RET.

But Intel cautions that this behaviour is not guaranteed, because new instructions can use an encoding that used to be a different instruction with an ignored prefix. e.g. LZCNT (encoded as REP BSR) produces the opposite result to BSR, so old code that included a REP BSR for some reason would stop working on new CPUs.

Note that on original 8086, rep mul/imul negates the result!! So historically it hasn't always been completely ignored, and that's probably why Intel only ever documents the ignoring for specific cases when the backwards-compatibility is actually useful (like rep nop = pause, stuff like HLE and BND prefixes, as well as TZCNT = BSF for non-zero inputs.) See also my and other answers on a retrocomputing Q&A.


rep and repe have the same opcode; rep is valid for the INS, OUTS, MOVS, LODS, and STOS instructions; repe/repne is valid for CMPS and SCAS instructions (which do affect the zero flag).

Because their opcodes are the same, repe is just the same as rep naturally; technically, you can't use repne in front of MOVS instructions, though it seems like the processor just treats it the same as rep (at least on the processor you tried).

TL;DR: repne movsb is an invalid/undocumented instruction and all bets are off. You shouldn't rely on it. repe movsb is technically invalid but your assembler encodes it exactly as rep movsb.

Source.