opcode

1.指令编码(硬编码)的结构图

详细表格见Intel手册卷2 B————>APPENDIX A OPCODE MAP————>ONE, TWO, AND THREE-BYTE OPCODE MAPS

2.前缀指令 (分四组,最多四个,每组最多一个)

LOCK 和 REPEAT前缀指令:

段前缀指令:

操作数宽度前缀指令:

地址宽度前缀指令:

3.经典定长指令-修改寄存器ERX (ERX代表8个通用寄存器)

PUSH/POP (指令大小1byte)

INC/DEC (指令大小1byte)

MOV Rb, Ib ( 指令大小2byte . Rb为16位通用寄存器,Ib为 Immediate Byte 一字节立即数)

MOV ERX, Id ( 指令大小5byte . Id为 Immediate Dword 四字节立即数)

XCHG EAX, ERX (指令大小1byte)

4.经典定长指令-修改EIP

1、0x70 - 0x7F

条件跳转,后跟一个字节立即数的偏移(有符号),共两个字节。

如果条件成立,跳转到 当前指令地址 + 当前指令长度 + Ib

最大值:向前跳7f,向后跳80

2、0x0F 0x80 - 0x0F 0x8F

条件跳转,后跟四个字节立即数的偏移(有符号),共五个字节。

如果条件成立,跳转到 当前指令地址 + 当前指令长度 + Id

最大值:向前跳7FFFFFFFF,向后跳80000000

3、其他指令

0xE0 LOOPNE/LOOPNZ Ib (Jb) 共2字节

0XE1 LOOPE/LOOPZ Ib (Jb) 共2字节

0XE2 LOOP Ib (Jb) 共2字节

0XE3 JrCXZ Ib (Jb) (在32位模式中,rCX为ECX) 共2字节

0xE8 CALL Id (Jd) 共5字节

0xE9 JMP Id (Jd) 共5字节

4、其他指令

8个段寄存器: ES CS SS DS FS GS LDTR TR (顺序固定)

0xEA JMP Ap (Ap:六字节长度的直接地址) 共7字节

0xEB JMP Ib (Jb)

0xC3 RET 共1字节

0xC2 RET Iw 共3字节

0XCB RETF (return far) 共1字节

0xCA RETF Iw 共3字节

5.经典变长指令-ModR/M字段

下面以MOV的变长指令举例

当指令中出现内存操作对象的时候,就需要在操作码后面附加一个字节来进行补充说明,这个字节被称为ModR/M. 该字节的8个位被分成了三部分:

其中,Reg/Opcpde (第3,4,5位,共3个字节) 描述指令中的G部分,即寄存器(Reg/Opcpde 也有可能用来描述操作码,看第一个opcode来具体分析)

Mod(第6,7位)和R/M(第0,1,2位)共同描述指令中的E部分,即寄存器/内存

那么,这8个位具体是如何工作的呢,Intel操作手册给出了一张表

前面我们已经讨论了Reg/Opcode部分(即3,4,5位)是怎样描述寄存器的,接下来我们重点说一下Mod和R/M是怎样合作描述寄存器/内存的

当 Mod == 0 时,ModR/M字节通过寄存器直接进行内存寻址

例如当操作指令为 88 01 时,其对应的汇编为MOV BYTE PTR DS:[ECX],AL

88 是操作指令,其后跟随的01为ModR/M

0x88描述了操作数宽度为b(byte),且操作数的顺序为Eb Gb,所以这条汇编指令为MOV BYTE PTR DS:[ECX],AL

同理可以分析出如下操作指令对应的汇编指令

1,ESP指向栈顶。是浮动的,不确定的。Intel将这个编码废弃,由另外的格式说明。

2,EBP指向栈底,而[EBP]通常存储上一个EBP,所以[EBP]无数据操作意义,Intel将这个编码废弃,改为立即数寻址

6.经典定长指令-SIB字段

ModR/M字段是用来是用来进行内存寻址的,可当地址形如DS:[EAX+ECX*2+12345678]时,仅仅靠ModR/M字段是描述不出来的。这时就在ModR/M后面增加一个SIB字节,与ModR/M字段共同描述。

下图是之前没有涉及到的三种情况:

这三种情况表示,在ModR/M字节后,还紧跟着一个SIB字节,SIB字节的8位被分成了三部分:

在例子DS:[EAX+ECX*2+12345678] 中,Scale描述 2^1 ,Index 描述ECX,Base描述EAX,而12345678 由ModR/M字段决定。

所以SIB字段描述的方式为:

Base + Index * 2^Scale (Scale描述2^Scale 所以只能为 *1 *2 *4)

下面我们通过分析指令,看看SIB是怎么工作的

MOV BYTE PTR DS:[EAX+ECX*2+12345678] ,AL

操作码

这条指令的原型为MOV Eb Gb ,所以操作码为0x88。且操作数中有Eb,所以必然存在ModR/M字段

ModR/M字节

1.Gb为AL,所以Reg/Opcode部分为000

2.内存地址为 寄存器 + I32 的格式,所以Mod部分为10, 偏移为 78563412

3.内存地址中寄存器部分多个寄存器,即在ModR/M字节后,还跟随着SIB字节,所以R/M部分为100

由此,ModR/M字节为0x84

SIB字节

1.DS:[EAX+ECX*2+12345678]中,Base对应着EAX,所以Base部分为000

2.Index对应着ECX,所以Index部分为001

3.Scale对应着21,所以Scale部分为01

由此,SIB字节为0x48

以上,可总结为如下图

由上,可得出指令编码为 88 84 48 ,再加上偏移12345678,完整的指令编码为88 84 48 12 34 56 78

SIB字段的图表如下

由此也可以推出,ModR/M整个字段,最长是6个字节

Last updated

Was this helpful?