不是全部的指令都是,看到opcode就知道有多长(定长指令),当指令中出现内存操做对象的时候,就须要在操做码后面附加一个字节来进行补充说明,这个字节被称为ModR/M。编码
该字节的8个位被分红了三部分:操作系统
其中,Reg/Opcode(第三、四、5位,共3个字节)描述指令中的G部分,即寄存器3d
Mod(第六、7位)和R/M(第0、一、2位)共同描述指令中的E部分,即寄存器/内存code
因特尔白皮书:对象
0x88 MOV Eb, Gb G:通用寄存器blog
0x89 MOV Ev, Gv E:寄存器/内存内存
0x8A MOV Gb, Eb b:字节im
0x8B MOV Gv, Ev v:Word, doubleword or quadword(这个看操做系统,是多少位就多少位)d3
MOV Eb, Gb: Gb决定了是8位的通用寄存器,具体是哪个通用寄存器还要看ModR/M的3,4,5部分总结
01:00 000 001
前两位是Mod ;3,4,5位是Reg/Opcode;0,1,2位是R/M
由上面能够知道 Reg/Opcode部分是 000,至关于0号寄存器,即[EAX],可是因为是8位,因此是AL
012位和67位组合起来是00 001
是[ECX],因此这条指令应该是:mov byte ptr ds:[ECX],AL
MOV Eb, Gb: Gb决定了是8位的通用寄存器,具体是哪个通用寄存器还要看ModR/M的3,4,5部分
01:00 010 101
前两位是Mod ;3,4,5位是Reg/Opcode;0,1,2位是R/M
由上面能够知道 Reg/Opcode部分是 001,至关于2号寄存器,即[ECX],可是因为是8位,因此是CL
012位和67位组合起来是00 101
能够看到这里并非咱们想的EBP,这是由于EBP指向栈底,而[EBP]一般存储上一个EBP,因此[EBP]无数据操做意义,Inter将这个编码废弃,改成当即数寻址
例如当操做指令为88 81 12 34 56 78时,其对应的汇编为MOV BYTE PTR DS:[ECX+78563412],AL
disp32其实是个偏移
再看这几个 ESP都没有对应的值
这是由于:ESP指向栈顶,是浮动的,不肯定的,Inter将这个编码废弃,由另外的格式来讲明。
仍是看一下
MOV Ev, Gv : Gv与我当前的x32dedug决定了是32位的通用寄存器,具体是哪个通用寄存器还要看ModR/M的3,4,5部分
01:00 000 011
前两位是Mod ;3,4,5位是Reg/Opcode;0,1,2位是R/M
由上面能够知道 Reg/Opcode部分是 000,至关于0号寄存器,即EAX
012位和67位组合起来是00 011
因此是[EBX],这条指令是:mov dword ptr ds:[ebx],eax
这里只列举一个,这个指令与0x88区别就是位数的差异
MOV Gb, Eb: Gb决定了是8位的通用寄存器,具体是哪个通用寄存器还要看ModR/M的3,4,5部分
01:00 000 111
前两位是Mod ;3,4,5位是Reg/Opcode;0,1,2位是R/M
由上面能够知道 Reg/Opcode部分是 000,至关于0号寄存器,即EAX,但咱们这里是byte因此是al
012位和67位组合起来是00 111
是EDI,这条指令命令为:mov al,byte ptr ds:[edi]
MOV Gv, Ev : Gv与我当前的x32dedug决定了是32位的通用寄存器,具体是哪个通用寄存器还要看ModR/M的3,4,5部分
01:00 100 110
前两位是Mod ;3,4,5位是Reg/Opcode;0,1,2位是R/M
由上面能够知道 Reg/Opcode部分是 100,至关于5号寄存器,即ESP
012位和67位组合起来是00 110
esi,mov esp,dword ptr ds:[esi]
MOV Gv, Ev : Gv与我当前的x32dedug决定了是32位的通用寄存器,具体是哪个通用寄存器还要看ModR/M的3,4,5部分
01:01 100 110
前两位是Mod ;3,4,5位是Reg/Opcode;0,1,2位是R/M
由上面能够知道 Reg/Opcode部分是 100,至关于5号寄存器,即ESP
012位和67位组合起来是01 110
[esi+12],mov esp.dword ptr ds:[esi+12]
当Mod = 00时,ModR/M字节经过寄存器直接进行内存寻址
当Mod = 01时,ModR/M字节经过寄存器+I8进行内存寻址(I为当即数,即8位当即数)
当Mod = 10时,ModR/M字节经过寄存器+I32进行内存寻址
当Mod = 11时,ModR/M字节直接操做两个寄存器