我即将进行一次组装测试,在准备过程中,我发现了一些奇怪的东西。repe movsb
在ZF = 0时重复,并且我被告知repe
应该在CX不等于0且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
最佳答案
在机器代码中,实际上只有两个不同的前缀字节。
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和其他答案。