http://hi.baidu.com/%C4%BD%C8%DD%CC%EC%D3%EF/blog/item/33ea77063832b1d07acbe1c8.html
http://computerscience.ycool.com/post.1801408.html
Intel的IA32-x86体系结构CPU的每条指令都可能由以下六个域组成,并且它们在指令中的排列顺序是不能改变的。
这六个域分别是:
prefixes (1 Byte)
code (1/2/3 Bytes; 2字节指令是第一个指令码为0x0f,而一般3字节指令的第3字节是ModR/M的一部分)
ModR/M (1 Byte)
SIB (1 Byte)
displacement (1/2/4 Bytes) 偏移量
immediate (1/2/4 Bytes) 立即数
在任何一条指令中code域必须出现,其他的域都是可选的。
由于这六个域在指令中的排列顺序是固定的,所以反汇编机器码,就是一个对它们的依次识别过程。
1、对prefixes的识别
x86体系结构CPU的4类prefixes,它们分别为:
lock/repeat prefix :F0/F2,F3 (LOCK和REP)
segment override prefixes :2E,36,3E,26,64,65 (段优先前缀)
operand-size override prefix :66 (忽略操作数大小的前缀)
address-size override prefix :67 (忽略地址大小的前缀)
也有人这样子分:
lock prefix :F0
repeat prefixes :F2,F3
segment override prefixes :2E,36,3E,26,64,65
operand-size override prefix :66
address-size override prefix :67
指令的prefixes可以由这几类prefixes组成,但是每类prefixes只能在指令中出现一次,至于每类prefixes在指令的出项顺序是没有要求的,这点和指令的六个域是不同的。当某类prefixes在同一指令中出现多次的时候,CPU在执行过程中,可能会出现不可预料的结果,至于会不会出现异常,Intel的官方手册中只用了这句话来说明:such use may cause unpredictable behavior.鬼知道会出项什么情况,因此算法必须对这类机器码具有识别能力。但是也可能异常情况不会发生,在反汇编过程,遇到同一类prefixes出现多次的情况,以最后出现的prefix为准,进行机器码识别。
总结:
(1)Prefixes是唯一的一个可能出现在code之前的域。
(2)所有的Prefixes都只有1个字节。
(3)在一个OpCode中可能会有多个Prefixes。
(4)如果有多个Prefixes,那么它们的顺序可以打乱,不会有任何问题。
(5)如果Prefixes不能对随它之后的OpCode起作用,那么它就会被忽略。
prefixes识别的核心代码:
for( ; nSizeOfCode > 0; nSizeOfCode--, pCode++)
{
IsPrefix = 1; //这个是用来判断当前机器码是不是prefixes
switch(*pCode)
{
case 0xF0:
if(lockPrefix == 0) lockPrefix = 0xF0;
else isPrefixRepeat = 1; //同一类重复出现
break;
... //这里的代码略了,但是这个地方要注意的是,对一类prefixes中有几个prefix的情况,
//这几个prefix共用一个是不是重复出现的标识(lockPrefix是lock prefix的重复出现标识)
default:
IsPrefix = 0; //不是prefixes机器码了
break;
}
if(IsPrefix == 0) break; //表示prefixes识别结束
}
if(isPrefixRepeat == 1) //说明指令的执行可能会发生异常
说明:lock prefix是用来在多处理器机器上保证对共享内存的互斥访问的,在反汇编的过程中,可以忽略这个前缀。