不幸的是,x86 编码复杂且不规则,理解它是一项艰巨的工作。编码的最佳“快速入门”是 sandpile.org 上的一组 HTML 页面(它很简洁,但非常全面)。
首先:http ://sandpile.org/x86/opc_enc.htm - “指令编码”表显示了十几种指令编码方式。每行中的白色单元格代表指令中的强制字节;根据操作码中较早出现的各种字段,存在(或不存在)以下灰色单元格。您应该查看以白色“0Fh”开头的行以及第一行。在同一页面的底部是出现在各种“扩展”操作码字段中的位域 - 您忽略了除“modrm/sib”行(第一行)之外的所有内容。
请注意,对于除第一行(即 1 字节操作码)之外的所有行,“mod r/m”字节必须跟在操作码之后(对于 1 字节操作码,它取决于指令)。这对大多数 2 参数指令的参数进行编码。http://sandpile.org/x86/opc_rm.htm中的表具有以下含义:一个参数必须是寄存器,另一个参数可以是寄存器或内存间接(“reg”字段对寄存器进行编码, “mod”和“r/m”字段对另一个参数进行编码)。操作码的其他地方通常还有一个“方向”位,指示参数的顺序。操作码还指示我们是否正在操作,例如 AL、AX、EAX 或 RAX(即不同大小),或扩展寄存器之一,
在 modrm 中,如果“mod”位为“11”,则“r/m”字段也指寄存器。否则,它通常指的是通过将命名寄存器添加到出现在 modrm 字节之后的(可选)位移来构造的内存地址(此常量的长度为 0、1 或 4 字节,具体取决于“mod”位)。例外情况是当“r/m”位为“100”(即 0x4)时,通常命名为“SP”——在这种情况下,内存参数由紧跟 modrm 字节的附加“sib”字节描述(任何 modrm 位移出现在 sib 之后)。对于 SIB 的编码,请查看http://sandpile.org/x86/opc_sib.htm,或从 modrm 页面单击。
最后,要了解方向和大小的来源,请查看一些操作码:http ://sandpile.org/x86/opc_1.htm 。前四个条目都是“ADD”,参数有两种不同的顺序,并且有两种不同的宽度。所以在这种情况下,指令的低位编码方向和宽度。