assembly - 如何根据实模式偏移和寻址确定 x86 机器操作码值?

标签 assembly x86 machine-code opcode instruction-encoding

我试图将原始机器码字节作为 0 和 1 写入文本文件,并通过 BIOS 执行它。

然而,我在理解寻址、乘法、偏移、寻址、操作数和指令如何在组合排列中工作时遇到了一些问题,即 MOV AL, 07 之间的差异和 MOV BL, AL .

我的意思是它在汇编中是有意义的,但是在机器代码中,获得参数的想法变得非常困难。

所以我想知道的是:我怎样才能更好地理解这一点?我发现没有任何教程可以准确地解释/描述数据传递、MMIO、寻址模式、算术等之间的组合相关性或连接中的指令中的 0 和 1。

在本站 http://ref.x86asm.net/coder32.html#x00它尝试,但我不明白这一点。

示例:假设我想将 5 移入 AL ...我是否将二进制文字“5”指定为与 AL/MOV 指令链接的二进制前缀中的操作码的一部分,或者我是否会为每个指定一个固定的二进制代码指令,不管值(value)?这就是我想知道的……如何理解机器代码的编写方式。

最佳答案

不幸的是,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(即不同大小),还是扩展寄存器之一,这就是为什么每个 3 位字段被列为引用许多不同寄存器的原因。

在 modrm 中,如果“mod”位是“11”,那么“r/m”字段也指的是一个寄存器。否则,它通常指的是通过将命名寄存器添加到出现在 modrm 字节之后的(可选)位移(此常量为 0、1 或 4 个字节长,具体取决于“mod”位)而构造的内存地址。异常(exception)是当“r/m”位为“100”(即 0x4)时,通常将其命名为“SP”——在这种情况下,内存参数由紧跟在 modrm 字节之后的附加“sib”字节描述(任何 modrm 位移出现在同胞之后)。 SIB的编码见http://sandpile.org/x86/opc_sib.htm ,或从 modrm 页面单击。

最后,要了解方向和大小的来源,请查看一些操作码:http://sandpile.org/x86/opc_1.htm .前四个条目都是“ADD”,参数有两种不同的顺序,并且有两种不同的宽度。所以在这种情况下,指令的底部位是编码方向和宽度。

关于assembly - 如何根据实模式偏移和寻址确定 x86 机器操作码值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18646509/

相关文章:

c - GCC 内联汇编没有将数据复制到输入寄存器

linux - 素数的逻辑错误

php - 机器码和操作码有什么区别?

assembly - 帧指针 MIPS 的使用

assembly - x86 汇编器中 "data label"的功能是什么?

assembly - 为什么要避免使用 POPF 来恢复中断标志状态?

c - 在给定汇编代码的情况下查找丢失的 C 代码?

assembly - I386指令集中GRPL指令的作用是什么?

assembly - arm-thumb指令集的blx指令如何支持4MB范围

unicode - 如何将 UTF-16 转换为 ASCII