1 机器码 的结构 {
机器码 有6 个域,分别是:
1. Prefixes (这个域中Prefixes 的顺序可以被打乱)
2. OpCode (是必须的)
3. Byte ModRM
4. Byte SIB
5. Diaplacement
6. imm Operand
其中:
Code 域是必须的,其他域可选。6 个域的顺序绝对不能乱(出现的域,编号小的必须在编号大的之前)。
}
2 一条指令的开始和结束:
2.1 开始:CPU 查看EIP,EIP 指向的地址被认为是一条指令的第一个字节。
2.2 结束:CPU 解码机器码(多半是OpCode),计算指令该在哪里结束。如果该指令不是控制类型的指令(改变EIP 的指令),那么指令结束的下一个字节将被认为是下一条指令的开始。
3 Prefixes:
性质:
它是唯一在Code 域之前的域,包含一个或多个Prefixes,每一个Prefixes 只有一个byte。如果Prefixes 无法对其后的OpCode 生效,那么该Prefixes 将会被忽略(例如 rep inc eax中,rep 将会被忽略)。
3.1Prefixes 0x66:用于切换默认操作数的大小。默认操作数如果是 32位,那么Prefixes 0x66 将会切换到16 位操作数。所以:在默认操作数是32 位的OS 上,任何操作word 的指令都较操作dword 的指令长一个字节(Prefixes 0x66),并且会多花一个时钟周期去执行。这里的默认操作数由描述符的D/B 位决定:当TYPE 属于 (0x8-0xf] 时段为CS,此时为D 位,代表Default operand size,置位表示默认值是32 位地址(Prefixes 0x67) 和 32 位或8 位操作数(Prefixes 0x66),复位表示默认值是16 位地址 和 16 位或8 位立即数。
3.2 Prefixes 0x67:用于切换默认地址的大小。和Prefixes 0x66 类似。
3.3 Prefixes 0xF2、0xF3:Rep Prefixes。其中0xF2 表示Repne (0 == ecx || 1 == ZF),0xF3 表示Rep/Repe (0 == ecx || 0 == ZF)。如果一条指令对ZF 没有影响,那么0xF3 表示Rep,否则表示Repe。当然对于不改变ZF 的串指令,0xF2 和0xF3 是一样的。
3.4 Prefixes 0x2E、0x3E、0x26、0x36、0x64、0x65 {
这些Prefixes 人称Segment Override Prefixes,用于改变默认段。
其中:
Prefixes | 对应的段 | 该段的默认指令组 |
0x2E | CS | EIP 寄存器 |
0x3E | DS | 串操作指令的源操作数在DS |
0x26 | ES | 目的操作数在内存单元的串指令 |