五 Prefixes 67h,F2h,F3h
五 Prefixes 67h,F2h,F3h
在上一篇教程里我们学习了有关Prefixes的一般特性:
1.所有的Prefixes都只有1个字节.
2.在一个OpCode中可能会有多个Prefixes.
3.如果Prefixes不能对随他之后的OpCode起作用,那么它会被处理器忽略.
我们举例学习了Prefixes 66H的作用和用法切换默认操作数大小.
现在我们学习另外的Prefixes,看看它们是否有什么好玩的地方可以影响我们的应用程序的执行.
Prefixes可以被划分为5个集合:
1. Change default operand size (66h)
2. Change default address size (67h)
3. Rep. prefixes (F3,F2)
4. Segnment specifying (change DEFAULT segment)(2e,36,3e,26,64,65)
5. Bus lock (F0)
Prefixes 66H
我们已经在之前的教程里面学习过.
一个测试题:
下面哪一个指令可以在32位应用程序中拥有66H Prefix:
scasb
scasw
scasd
你可以在调试器里输入这些操作码来检验你的答案.
(提示:答案是scasw)
Prefixes 67H
改变默认地址大小.
输入助记符
mov al,[eax]
可以看到
8A00 MOV AL,[BYTE DS:EAX]
现在再输入以67H开头的OpCode.
67:8A00 MOV AL,[BYTE DS:BX+SI]
1.可以看到相应的字节已经被16位的寄存器bx, si寻址.在32位寻址模式中所有的数据都被32位的地址确定,包括32位基址,32位索引,32位偏移.在16位模式中这些都是16位的.
2.可能你还注意到地址部分并不是变为mov al,[ax],而是变成了[bx][si].为什么呢?我们将在学习[mod r/m]和[sib]的时候给出答案.
现在我们可以暂时认为,在16位地址模式中无法像32位地址模式一样使用所有的基址寄存器和索引寄存器,OpCode用来指定寻址的寄存器的位域也是不同的.
不知道你是否需要常在32位环境下使用16位的寻址模式,不用担心,我们会深入的学习这个。在32位环境下使用16位的寻址模式可能会非常高效,不过这个需要你去控制总的地址范围不能超过0FFFF(一个内存页面的大小4kb)。
Rep. Prefixes F2, F3
如果你了解串操作指令(如movs, scas, lods 等),你一定知道什么时候使用rep\repe\repne前缀.
一些串操作指令只能使用前缀rep(如movsb, lodsb----在计数器e(cx)=0的时候终止;另一些则可以使用repe或repne----在计数器变为0并且ZF标志位不满足前缀指定的条件的时候结束.换句话说repne在ZF=1而repe在ZF=0的时候终止.当然它们都会在满足ecx=0而当ZF=0或1的时候各有不同.
有两点规则:
1. 你可以看到有3种Rep prefixes助记符:rep,repe,repne,但是只有2个OpCode:F2,F3
2. 如果某些指令只使用前缀rep,那么这里的rep可以用repe或者repne来代替.这种情况下
Rep Lodsb
Repe Lodsb
Repne Lodsb
按照同样的方式运行:它们会重复运行指令LODSB共ecx(cx)次,而不管prefix是F2还是F3.
我们可以验证一下:
xor eax,eax ;使ZF = 0
mov esi,esp ;esi指向栈顶
mov ecx,10
repe lodsb ;opcode with repe and rep indentical - F3
mov esi,esp
mov ecx,10
repne lodsb
按F7或F8运行后可以看到它们的作用是一样的.
只有在可能会改变某些标志位的重复串指令时,F2和F3才会表现出不同,如scasb.在这种情况下,有些指令与重复前缀操作搭配使用,F2和F3会把最后一位与标志位ZF进行比较,如果它们不相同,则重复串指令的操作将会结束.而有些指令不用进行这个比较的操作,因此标志位ZF对这些指令的运行结果无影响.只需将F2(1111 0010)和F3(1111 0011)用二进制表示你就会明白我的意思.
(提示:F2(1111 0010)的最后一位是0,指令执行的时候CPU会将F2的最后一位0与ZF标志位比较,如果此时e(cx)为0,并且ZF为1,与F2最后一位不同,则指令不在重复;否则重复。F3同理)
下次我们将完成对prefixes的讨论并且我们将进一步学习改变EIP的OpCode.
原文第五帖
