x86/x64指令编码内幕(适用于AMD/Intel)【转自】目录1.序言---用2个实例来开启x86/x64指令编码的感观世界.........................................................................22.指令格式.................................................................................................................................................................43.深入了解prefix......................................................................................................................................................84.REXprefix...............................................................................................................................................................245.指令opcode码...................................................................................................................................................366.ModRM寻址模式................................................................................................................................................457.SIB补充寻址........................................................................................................................................................528.displacement值....................................................................................................................................................579.immediate值........................................................................................................................................................6110.指令的解析...........................................................................................................................................................64附录1:ModRM与SIB设计上的2个原则................................................................................................................67附录2:default(缺省)与effective(有效)...............................................................................................................70附录3:指令的operandsize............................................................................................................................................75附录4:x86/x64指令的编码构造........................................................................................................................................79附录5:x87浮点指令格式...................................................................................................................................................90附录6:x87浮点指令的编码方式.......................................................................................................................................91附录7:x87指令解析...........................................................................................................................................................951.序言---用2个实例来开启x86/x64指令编码的感观世界1.在当前32位系统下,有下面汇编语句(Intel格式):movwordptres:[eax+ecx*8+0x11223344],0x12345678注1:“32位系统下”指的是:指令的defaultoperandsize(默认操作数宽度)为32位!(CS.D=1)从这条语句,我们可以得出以下信息:这是一条mov指令firstoperand(目标操作数)是memorysecondoperand(源操作数)是immediate对于memory操作数,我们还了解到:operandsize(操作数大小)是wordaddresssize(地址大小)是32位memmory寻址是[base+index*8+displacement32]对于immediate操作数,我们了解到:它的值为0x12345678,因此,我们可以判断它的operandsize是DoubleWord(32位)!显然:firstoperand(目标操作数)的operandsize大小是word(2个字节),而secondoperand(源操作数)却是一个doubleword大小的0x12345678,在这条指令中存在operandsize不兼容的情况。那么:对于这条汇编语句,编译器应该如何处理呢?应该怎样处理immediate部分应该选择哪条mov指令指令最终的operandsize是多少在32位环境下,如何生成16位operand或address的代码寻址模式是什么这些问题是我们最终需要掌握的知识,这是本栏目的最终目的。实际上,大多数的编译会最终形成这样的机器编码是:2666c784c84433221178561.doubleword大小的“立即数操作数”,会被编译器截断为word大小,形成值0x56782.选择MOVEv,Iz指令,它的opcode是C73.最终指令的operandsize是word大小,取决于firstoperand的size4.由于默认的operandsize是32位,编译器通过插入operandsizeoverrideprefix(66H)可以改写为16位operandssize!(注2:可以使用addresssizeoverrideprefix(67H)来来改写为16位addresssize!)5.它的寻址模式是:基址+变址+disp32寻址,它需要提供SIB字节下面的图直观的分解这条指令的组成部分:2.指令格式在序言里的例子稍作修改:movdwordptres:[eax+ecx*8+0x11223344],0x12345678将wordptr指示字改回dwordptr,这是个具有典型指令编码意义的指令。它的encodes(机器编码)是:26c784c84433221178563412(共12个字节)。1.编码序列如上图所示:这是x86/x64体系的General-PuposeInstruction(通用体系指令)的编码格式,记住这个编码序列很重要,这是解析指令编码的基石。这个编码序列分为:1.LegacyPrefix2.REXprefix3.Opcode4.ModRM5.SIB6.Displacement7.Immediate按功能组别,我将这个指令序列分为4个部分:PrefixOpcodeModRM与SIBDisplacement与Immediate其中,只有opcode是必须的,其它组成部分都可选!1.1Prefix(前缀)AMD推出x86扩展64位技术时,增加了一个用于访问扩展的64位数据prefix,它是:REXprefix而x86原有的prefix则变为了指令格式中的:LegacyprefixREXprefix仅存在于x64的64-bit模式中,在legacyx86模式下,REXprefix是无效的,但是在x64的64-bit模式下Legacyprefix是有效的。REXprefix的取值范围是:40H-4FH在非64位模式下,它们是inc与dec指令,也就是说这些指令在64位模式下被重定义为REXprefix1.2Opcode(操作码)大多数通用指令的Opcode是单字节,最多是2字节。但是对x87FPU指令和SSEx等SMID指令来说可以有3个字节的,Opcode码代表着指令是做什么操作。一些Opcode并不是完整的Opcode码,它需要ModRM字节进行辅助,这类型的Opcode被分成以Group(组)为单位的一组Opcode,同一组的Opcode有着相同的operand属性。1.3ModRM与SIBModRM字节为指令提供operand的寻址。从某个角度看可以认为是operand的属性!包括:operand类型operandsize某些Opcode还需要ModRM字节进行辅助,ModRM的结构分为三部分:ModRM[7:6]-Mod部分ModRM[5:3]-Reg部分ModRM[2:0]-R/M部分ModRM.mod提供operand的寻址模式,可以从memory或register中进行选择,ModRM.reg提供具体register的ID值,ModRM.r/m可以选择Register/Memory寻址由ModRM.mod决定。也就是:提供register的ID值,或者内存寻址中的base寄存器的ID值!SIB提供memory操作数中的b