我即将进行一次组装测试,在准备过程中,我发现了一些奇怪的东西。repe movsb在ZF = 0时重复,并且我被告知repe应该在CX不等于0且ZF = 1时重复。
我进行了一些测试,发现在movsbrepreperepne指令之前,它们是相同的。
这有什么解释?

编辑:
这是代码:

.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

最佳答案

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

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

  • 英特尔的insn reference manual REP entry仅记录MOVS的F3 REP,而不记录F2前缀。恭喜,您已经找到了REP MOVSB的未记录编码,至少在您对其进行测试的任何CPU上都是如此。 :)
    另请参见this appendix of the NASM manual,其中包括其他未记录的操作码,但不包括此F2 A4 REPNE MOVSB。 (从x86标签Wiki链接)。

    通常,不会影响指令的前缀会被忽略,因此我希望REPNE MOVSB的运行方式与MOVSB相同。例如TZCNT编码为REP BSF,在不支持BMI1的CPU上,它简单地作为BSF执行。 (除了源为零时,执行相同的操作。)
    同样,REP RET是引入padding to work around a limitation of AMD K8/K10 branch predictors的常见技巧,其运行方式与RET相同。
    但是Intel警告说,这种行为无法得到保证,因为新指令可以使用一种编码,该编码曾经是具有不同前缀的另一条指令。例如LZCNT(编码为REP BSR)产生与BSR相反的结果,因此由于某种原因包含REP BSR的旧代码将停止在新CPU上工作。
    请注意,在原始8086上, rep mul/imul negates the result !!因此,从历史上看,它并没有一直被完全忽略,这也许就是为什么英特尔只记录了当向后兼容确实有用的情况下才忽略的特定情况(例如rep nop = pause,HLE和BND前缀之类的东西以及TZCNT =非零输入的BSF。)另请参阅retrocomputing Q&A上的my和其他答案。

    10-01 15:18