我很快就进行了装配测试,在准备的时候,我发现了一些奇怪的东西
repe movsb
在ZF = 0时重复,我被告知repe
应重复,而CX不等于零且ZF = 1。
我做了一些测试,发现在movsb
之前,rep
,repe
和repne
指令的工作方式相同。
对此有何解释?
编辑: 这是代码:
.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
答案 0 :(得分:3)
rep
和repe
具有相同的操作码; rep
对INS,OUTS,MOVS,LODS和STOS指令有效; repe
/ repne
对CMPS和SCAS指令有效(这会影响零标记)。
由于他们的操作码相同,repe
自然与rep
相同;从技术上讲,你不能在MOVS指令前面使用repne
,尽管看起来处理器只是像rep
那样对待它(至少在你试过的处理器上)。
TL; DR:repne movsb
是无效/未记录的指令,所有投注均已关闭。你不应该依赖它。 repe movsb
在技术上无效,但您的汇编程序将其编码为rep movsb
。
答案 1 :(得分:2)
在机器代码中,实际上只有两个不同的前缀字节。
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。 (从x86标签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上工作。