当提到MODR/M BYTE时,8086的文档网站似乎有些模糊,并且很难理解它是什么和做什么。
MODR/M BYTE中使用的所有位是什么?可能的选项是什么?
我发现了一些文档:
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
什么是索引模式?什么是寄存器号?寄存器如何表示? ETC。
The 8086 documentation sites seem a bit vague when the MODR/M byte is mentioned and it's really difficult to comprehend what it is and does.
What are all the bits used for in the MODR/M byte and what are the possible options?
Some documentation I've found: 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
What is an indexing mode? What is a register number? How is a register represented? etc.
发布评论
评论(1)
英特尔自己的PDF手册详细记录了这一点;参见,特别是每个说明条目之前的介绍章节。
在各个站点上也有详细的描述-64_instruction_encoding#modr.2fm_and_sib_bytes (覆盖16-乘以的modrm,因此不仅在谈论x86-64长模式。向后的组合是x86的全部点,也是为什么如此讨厌的原因。
当然,您可以找到实际8086手册本身的PDF副本,以防省略仅与其他模式相关的内容更有帮助。
第23页的8086底漆涵盖了操作数的指令。它写为一本书,而不仅仅是技术手册。它可以在Stephen Morse的网站上免费提供( https://stevemorse.orge.org/8086/ ),当他在英特尔时设计它的家伙。
但是,也许这有助于描述MODRM目的的基本概述,因此您知道在这些文档中要寻找什么。
MODR/M的目的和基础知识
(但不是全部)X86指令具有一个MODRM字节。它可以为2个操作数编码,其中最多一个是内存或两个寄存器。例如
添加CX,AX
或添加CX,[BX+SI]
。OpCode本身确定R/M和R操作数的哪个是源和/或目标,或
/r
字段是否充当额外的OPCODE位。 (例如,对于轮班,这就是为什么他们不能复制和换档,也不能使用CLANCE以外的计数寄存器。)添加[BX+SI],CX
具有相同的ModRM字节与添加cx,[bx+si]
,但另一个opcode。仅寄存器操作数为3位 /R字段的代码。 3位可以为X86的8个通用寄存器中的任何一个中的任何一个。这是一个“寄存器号码”,就像在任何具有2^n寄存器的普通ISA中一样,每个指令代码中的n个位组中的n位。
r/m
操作数也可以是寄存器,但是2位“模式”字段确定3位R/M字段是寄存器号(mod = 0b11)还是它是否是内存地址模式。 (加上8或16位的位移,因此编码DESP0/8/16消耗了模式字段的其他3个编码。)https://wiki.osdev.org/x86-64_instruction_encodion_encoding#modr.2fm_and_sib_sib_sib_bytes 显示字段和口译为16位地址 - 登记式地址,包括16位地址数字。
因此,只有3个位可以为内存地址指定寄存器或寄存器组合。 386添加了sib字节的逃生代码,允许
[eax + ecx*4]
等全面选择地址模式,但是8086(和任何CPU上的16位地址)必须是某些的子集[BX | BP] + [Si | Di] + Disp0/8/16
。参见 8086中的通用寄存器之间的差异bx]作品,[cx]不? -scale-factor-whil-the-the-the-the-the-the-bit-vers'>为什么x86 16位地址模式不具有比例因子,而32位版本则具有?
来自组装
的示例foo.asm
,然后ndisasm -b16 foo
,或要求nasm本身用nasm -l/dev/dev/stdout foo.asm
进行清单。然后进行编辑以简化输出字段。要创建更多示例,请使用汇编器自己创建机器代码。
另请参见
ff/2
呼叫R/M16呼叫R/M16靠近,绝对间接。Intel's own PDF manuals document this in detail; see vol.2 of the SDM, specifically the intro chapters before the entries for each instruction.
There are also detailed descriptions on various sites like https://wiki.osdev.org/X86-64_Instruction_Encoding#ModR.2FM_and_SIB_bytes (which covers 16-bit ModRM, so it's not just talking about x86-64 long mode.) Modern x86 uses the same instruction encoding (in 16-bit real mode) as 8086; that backwards compat is the whole point of x86, and why it's so nasty.
And of course you can get find PDF copies of the actual 8086 manual itself, in case that's more helpful to omit stuff that's only relevant for other modes.
The 8086 primer from page 23 onwards covers instruction encoding of operands. It's written as a book, not just a technical manual. It's available for free on Stephen Morse's web site (https://stevemorse.org/8086/), the guy who designed it when he was at Intel.
But maybe it would help to describe the basic overview of the purpose of ModRM, so you know what to look for in those docs.
ModR/M purpose and basics
Most (but not all) x86 instructions have one ModRM byte. It can code for 2 operands, up to one of them being memory, or both registers. e.g.
add cx, ax
, oradd cx, [bx+si]
.The opcode itself determines which of the r/m and r operands are the source and/or destination, or whether the
/r
field acts as extra opcode bits. (e.g. for shifts, that's why they can't copy-and-shift, or use a count register other than CL.)add [bx+si], cx
has the same ModRM byte asadd cx, [bx+si]
but a different opcode.The register-only operand is code by the 3-bit /r field. 3 bits can code for any of x86's 8 general-purpose registers. This is a "register number", like in any normal ISA with 2^n registers, groups of n bits in each instruction code for register operands.
The
r/m
operand can also be a register, but the 2-bit "mode" field determines whether the 3-bit r/m field is a register number (mod=0b11) or whether it's a memory addressing mode. (Plus an 8 or 16-bit displacement, so coding for a disp0/8/16 uses up the other 3 encodings of the mode field.)https://wiki.osdev.org/X86-64_Instruction_Encoding#ModR.2FM_and_SIB_bytes shows the fields and interpretation for 16-bit address-size, including register numbers.
So there are only 3 bits to specify a register or combination of registers for the memory address. 386 added an escape code for a SIB byte, allowing a full selection of addressing modes like
[eax + ecx*4]
, but 8086 (and 16-bit address-size on any CPU) must be some subset of[BX|BP] + [SI|DI] + disp0/8/16
.See Differences between general purpose registers in 8086: [bx] works, [cx] doesn't? / Why don't x86 16-bit addressing modes have a scale factor, while the 32-bit version has it?
Examples from assembling
foo.asm
and thenndisasm -b16 foo
, or from asking NASM itself to make a listing withnasm -l/dev/stdout foo.asm
. Then editing to simplify the output fields.To create more examples, use an assembler to create machine code yourself.
See also
/r
field of ModRM is used as extra opcode bits, likeFF /2
CALL r/m16 Call near, absolute indirect.