为什么 repe 和 repne 在 movsb 之前做同样的事情?

why do repe and repne do the same before movsb?

我马上要进行组装测试,在准备的过程中,我发现了一些奇怪的事情。
repe movsb 在 ZF=0 时重复,我被告知 repe 应该在 CX 不等于零且 ZF=1 时重复。
我做了一些测试,发现在 movsb 之前,repreperepne 指令工作相同。
对此有何解释?

编辑: 这是代码:

.model small
    .data
    A db   '   This     is    a    test '
    N  db  27
    .stack 10h
    .code
    mov ax,@data
    mov ds,ax
    mov es,ax
    cld
    mov al,' '
    mov cl,N
    xor ch,ch
    mov di,offset  A
    next:  repe scasb
    jcxz cont        ; jump if cx=0
    dec di
    inc cx
    xchg  si,di      ; swap between si and di
    push  cx
    push  di
    repe  movsb
    pop   di
    pop   cx
    repne scasb
    mov si,di
    jmp next
    cont: .exit
    end

reprepe 具有相同的操作码; rep对INS、OUTS、MOVS、LODS、STOS指令有效; repe/repne 对 CMPS 和 SCAS 指令有效(它们会影响零标志)。

因为他们的操作码相同,所以repe自然就和rep一样;从技术上讲,您不能在 MOVS 指令前使用 repne,尽管处理器似乎将其视为与 rep 相同(至少在您尝试过的处理器上)。

TL;DR: repne movsb 是一个 invalid/undocumented 指令,所有的赌注都关闭了。你不应该依赖它。 repe movsb 在技术上是无效的,但您的汇编程序将其编码为 rep movsb

Source.

在机器码中,其实只有两个不同的前缀字节。

  • 0xF3 与 MOVS/LODS/STOS/INS/OUTS 一起使用时称为 REP(不影响标志的指令)
  • 0xF3 与 CMPS/SCAS
  • 一起使用时称为 REPE 或 REPZ
  • 0xF2 在与 CMPS/SCAS 一起使用时被称为 REPNE 或 REPNZ,并且没有记录其他指令。

Intel 的 insn reference manual REP entry 仅记录 F3 REP 的 MOVS,而不是 F2 前缀。恭喜,您找到了 REP MOVSB 的未记录编码,至少在您测试过的 CPU 上是这样。 :)

另请参阅 this appendix of the NASM manual which includes other undocumented opcodes, but not this F2 A4 REPNE MOVSB. (linked from the 标签 wiki)。


通常情况下,不影响指令的前缀会被忽略,所以我希望 REPNE MOVSB 到 运行 与仅 MOVSB 相同。例如TZCNT 被编码为 REP BSF,在不支持 BMI1 的 CPUs 上,它简单地执行为 BSF。 (做同样的事情,除非源为零。)

同样,REP RET是引入padding的常用技巧to work around a limitation of AMD K8/K10 branch predictors,运行与RET相同

但英特尔警告说,这种行为并不能保证,因为新指令可以使用一种编码,而这种编码曾经是带有忽略前缀的不同指令。例如LZCNT(编码为 REP BSR)产生与 BSR 相反的结果,因此由于某种原因包含 REP BSR 的旧代码将停止在新的 CPUs 上工作。

请注意,在原始 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