罗聪 OpCode教程 笔记三

Prefixes!
http://www.luocong.com/learningopcode/doc/3._Prefixes_-_Part_I.htm

 
OpCode                          mnemonic
40                                     INC EAX
66 40                               INC AX

我们可以看到,40表示的是INC EAX,66 40表示的是INC AX,两者的分别在于:前者的操作数是32位的(EAX),而后者是16位的(AX)。

从OpCode的角度来看,后者比前者多了一个66,就导致了不同的结果,唔……Intel x86规定:

66是一个Prefix,我们把Prefix翻译为前缀,所谓前缀,就是与code进行组合用以产生出某些变化形式的“东西.

请记住这6个域

Prefixes
code
ModR/M
SIB
Displacement
Immediate

Prefixes的几个特性

1. 它是唯一的一个可能出现在code之前的域。
2. 所有的Prefixes都只有1个字节。
3. 在一个OpCode中可能会有多个Prefixes。 

看看刚才提到过的prefix 66,这个prefix的意思是“切换默认的操作数的大小”。

例如在有的系统中有2种默认的操作数大小:16位和32位。操作数有可能会被写成16位或者32位,唯一的区分方法是看它有没有prefix 66。

OpCode      mnemonic
66 AD          LODSW
AD                LODSD

依然假设默认的操作数是32位的,有没有发现什么不寻常的地方?

LODSW和LODSD的code域是一样的——都是AD!其实,LODSW和LODSD这两个指令是同一个指令,只不过它们的操作数大小不一样——LODSW使用了2个字节(16位)的WORD作为操作数,而LODSD则使用了4个字节(32位)的DWORD作为操作数。

如果默认的操作数大小是WORD(16位),那么切换后就是DWORD(32位);反之,如果默认的操作数大小是DWORD(32位),那么切换后就是WORD(16位)。

(在32位的系统中, 66代表使用16位, 而在16位的系统中, 66代表使用32位).

 

切记!Prefixes 66就像一个触发器一样,起的作用就是进行切换。

让我们再来看一个特例:

B0 FF    MOV AL, 0FF
8A C1    MOV AL, CL

看清楚了吗?现在的操作数是AL和CL,加上prefix 66后会如何?

66 B0 FF    MOV AL, 0FF
66 8A C1    MOV AL, CL

Faint!没有任何变化!

为什么呢? 也许并不是所有情况下的操作数大小都可以随意改变的。假如这个改变是不允许的,那么它就会被忽略

为了证实这个猜想,让我们来看看下一个更有趣的例子:

prefix F3(rep)的作用是让CPU对随后的指令循环执行ecx(cx)次,指令INC EAX的OpCode是40,好,如果我们想连续执行3次INC EAX的话,应该怎么样呢?

也许你会想当然地认为应该这样写:

xor eax, eax
mov ecx, 3
rep inc eax

实际上!并不是这样!这样的程序的运行结果是:

没有任何异常(exception)产生。
最后eax = 1,这意味着prefix F3并没有起作用——它被忽略了。
现在我们可以证实之前的想法:

如果Prefixes不能对随它之后的OpCode起作用,那么它就会被忽略。

再回忆一下之前提到的三个特性:

Prefixes是唯一的一个可能出现在code之前的域。
所有的Prefixes都只有1个字节。
在一个OpCode中可能会有多个Prefixes。
前面两点应该比较容易理解,让我们来看看第3点是什么意思。

如果想得到下面的指令:

REP LODSW

它的OpCode将会是:

66 F3 AD

解释如下:

66 AD:LODSW
F3: REP

都是前面讲过的内容,不难吧?只是组合起来使用罢了。

不过……细心的读者可能会问:为什么要把66放在第一位,把F3放在第二位呢?把它们的位置调换一下行不行?答案是:行!事实上它也可以写成:

F3 66 AD

效果是一样的!

 Prefixes的特性

 一个OpCode中可以有多个Prefixes。
 如果有多个Prefixes,那么它们的顺序可以打乱,不会有任何问题。 

最后,我们还可以得出一个推论:

由于每个Prefixes会多占用1个字节,所以也必定会导致处理器多使用一个指令周期进行解码——无论在时间还是空间上都会造成浪费。因此,我们应该权衡在哪些场合才使用Prefixes,如非必要,应该减少对它的使用。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值