8086指令集:MODR/M字节



当提到MODR/M字节时,8086文档站点似乎有点模糊,很难理解它是什么和做什么。

MODR/M字节中使用的所有位是什么,可能的选项是什么?

我找到了一些文档:https://www.scs.stanford.edu/05au-cs240c/lab/i386/s17_02.htm

The ModR/M byte contains three fields of information:
The mod field, which occupies the two most significant bits of the byte, combines with the r/m field to form 32 possible values: eight registers and 24 indexing modes
The reg field, which occupies the next three bits following the mod field, specifies either a register number or three more bits of opcode information. The meaning of the reg field is determined by the first (opcode) byte of the instruction.
The r/m field, which occupies the three least significant bits of the byte, can specify a register as the location of an operand, or can form part of the addressing-mode encoding in combination with the field as described above

什么是索引模式?什么是登记号码?寄存器是如何表示的?等。

英特尔自己的PDF手册详细记录了这一点;参见SDM第2卷,特别是每条指令条目之前的介绍章节。

在不同的网站上也有详细的描述,比如https://wiki.osdev.org/X86-64_Instruction_Encoding#ModR.2FM_and_SIB_bytes(它涵盖了16位ModRM,所以它不仅仅是在谈论x86-64长模式。)现代x86使用与8086相同的指令编码(在16位实模式下);向后比较是x86的全部意义,也是为什么它如此令人讨厌。

当然,你可以找到实际8086手册本身的PDF副本,以防省略只与其他模式相关的内容更有帮助。

从第23页开始的8086入门介绍了操作数的指令编码。这是一本书,而不仅仅是一本技术手册。可以在Stephen Morse的网站(https://stevemorse.org/8086/)上免费获得,他是在英特尔工作时设计的。

但是也许它会帮助描述ModRM目的的基本概述,这样你就知道在这些文档中寻找什么。


ModR/M用途和基础

大多数(但不是全部)x86指令有一个ModRM字节。它可以为两个操作数编码,最多一个是内存,或者两个寄存器。例如:add cx, ax,或add cx, [bx+si]

操作码本身决定r/m和r操作数中哪个是源和/或目的,或者/r字段是否作为额外的操作码位。(例如,对于移位,这就是为什么他们不能复制和移位,或者使用除CL以外的计数寄存器。)add [bx+si], cx具有与add cx, [bx+si]相同的ModRM字节,但操作码不同。

仅限寄存器的操作数由3位/r字段编码。3位可以为x86的8个通用寄存器中的任何一个编码。这是一个"寄存器号",就像在任何具有2^n个寄存器的普通ISA中一样,每个指令代码中有n位的一组用于寄存器操作数。

r/m操作数也可以是寄存器,但是2位模式是寄存器。字段确定3位r/m字段是寄存器号(mod=0b11)还是内存寻址模式。(加上一个8位或16位的位移,所以编码一个dis0/8/16会占用mode字段的其他3个编码。)

https://wiki.osdev.org/X86-64_Instruction_Encoding#ModR.2FM_and_SIB_bytes显示了16位地址大小的字段和解释,包括寄存器号。

所以只有3位来指定内存地址的寄存器或寄存器组合。386为SIB字节添加了一个转义码,允许像[eax + ecx*4]这样的寻址模式的完整选择,但是8086(在任何CPU上都是16位地址大小)必须是[BX|BP] + [SI|DI] + disp0/8/16的某个子集。

参见8086中通用寄存器之间的差异:[bx]工作,[cx]不工作't?/为什么x86 16位寻址模式没有缩放因子,而32位版本有?

从组装foo.asmndisasm -b16 foo的例子,或从要求NASM本身与nasm -l/dev/stdout foo.asm组成一个清单。然后编辑以简化输出字段。

00 00           add [bx+si],al      ; opcode=0x00 (add byte, mem dst)  mod=00 r=000 r/m=000
01 C0           add ax, ax          ; add r/m, r   mod=11 (register) r=000 (AX) r/m=0 (AX)
01 08           add [bx+si], cx     ; add r/m, r
03 08           add cx, [bx+si]     ; mod=0, r=001 (CX) r/m=000 ([bx+si])
03 0F           add cx, [bx]        ; mod=00 r=001 (CX) r/m=111 ([BX])
03 4F 04        add cx, [bx + 4]    ; mod=01 r=001 (CX) r/m=111  disp8=4
01 F2           add dx, si          ; mod=11 r=110 (SI) r/m=010 (DX)

要创建更多示例,请使用汇编程序自己创建机器码。

参见

  • 为什么x86 16位寻址模式没有缩放因子,而32位版本有?
  • rbp不允许作为SIB基地?-编码意味着[bp]实际上意味着没有基寄存器,只是位移。
  • 在Intel x86 Assembly文档中[——][——]是什么意思?(32/64位模式ModR/M和SIB).
  • 当ModRM的/r字段被用作额外的操作码位时,如FF /2CALL r/m16 CALL near, absolute indirect.

最新更新