opcode
Last updated
Last updated
详细表格见Intel手册卷2 B————>APPENDIX A OPCODE MAP————>ONE, TWO, AND THREE-BYTE OPCODE MAPS
LOCK 和 REPEAT前缀指令:
段前缀指令:
操作数宽度前缀指令:
地址宽度前缀指令:
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)
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字节
下面以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将这个编码废弃,改为立即数寻址
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个字节