为什么在movsb之前重复和重复做同样的事情?

时间:2016-10-24 13:17:36

标签: string assembly repeat

我很快就进行了装配测试,在准备的时候,我发现了一些奇怪的东西 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

2 个答案:

答案 0 :(得分:3)

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

由于他们的操作码相同,repe自然与rep相同;从技术上讲,你不能在MOVS指令前面使用repne,尽管看起来处理器只是像rep那样对待它(至少在你试过的处理器上)。

TL; DR:repne movsb是无效/未记录的指令,所有投注均已关闭。你不应该依赖它。 repe movsb在技术上无效,但您的汇编程序将其编码为rep movsb

Source

答案 1 :(得分:2)

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

    与MOVS / LODS / STOS / INS / OUTS(不影响标志的指令)一起使用时,
  • 0xF3被称为REP
  • 0xF3与CMPS / SCAS一起使用时称为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。 (从标签wiki链接。)

通常情况下,忽略不影响指令的前缀,因此我希望REPNE MOVSB只运行MOVSB。例如TZCNT编码为REP BSF,在不支持BMI1的CPU上,它简单地作为BSF执行。 (做同样的事情,除非源是零。)

类似地,REP RET是引入填充to work around a limitation of AMD K8/K10 branch predictors的常用技巧,并且与RET运行相同。

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