8086指令集MODR/M字节位定义、字段功能及寻址机制技术咨询
位结构与取值范围
ModR/M是x86指令中紧跟在1字节主操作码之后的寻址描述字节,总长度8位,从最高位(bit7)到最低位(bit0)划分为三个独立字段,各字段取值和功能如下:
mod字段:占最高2位(bit7、bit6),合法取值为二进制00/01/10/11,共4种,核心作用是和低位r/m字段共同确定操作数的寻址类型。reg字段:占中间3位(bit5、bit4、bit3),合法取值为二进制000到111,共8种,具体功能由主操作码决定:要么指定一个寄存器作为源/目的操作数,要么作为3位扩展操作码,区分主操作码相同的不同指令(比如算术运算、移位指令的不同变体)。r/m字段:占最低3位(bit2、bit1、bit0),合法取值为二进制000到111,共8种,和mod字段配合使用:当mod=11时直接指定寄存器操作数,其余取值下共同编码内存操作数的寻址规则。
现有公开文档对ModR/M字段的基础描述如下:
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
核心概念与编码规则
寄存器编号(register number)
3位长度的寄存器编号总共可以表示8个寄存器,具体映射的物理寄存器由当前指令的操作数位宽决定,同一编码在8位、16位操作数场景下对应不同寄存器,8086下的固定映射规则为:
- 8位操作数(字节操作)场景:
000=AL、001=CL、010=DL、011=BL、100=AH、101=CH、110=DH、111=BH - 16位操作数(字操作)场景:
000=AX、001=CX、010=DX、011=BX、100=SP、101=BP、110=SI、111=DI
举个实际例子:指令MOV DL, BL是8位操作,对应ModR/M中reg字段为010(DL)、r/m字段为011(BL)、mod字段为11(寄存器寻址),整字节值为0xC3;同样字段取值如果是16位操作的指令,对应操作数就变成DX和BX。
索引模式(indexing mode)
索引模式即内存操作数的有效地址计算规则,当mod≠11时,3种mod取值搭配8种r/m取值,总共编码24种内存寻址模式,8086下的具体组合规则没有歧义,对应规则如下:
mod=00:无位移量寻址。除r/m=110对应直接地址寻址(指令后紧跟16位内存有效地址)外,其余r/m对应无位移的基址/变址寻址:000=[BX+SI]、001=[BX+DI]、010=[BP+SI]、011=[BP+DI]、100=[SI]、101=[DI]、111=[BX]mod=01:带8位位移量寻址。所有r/m取值都对应「基址/变址寄存器 + 8位有符号位移」的有效地址计算方式,比如r/m=110对应[BP+disp8],r/m=000对应[BX+SI+disp8],位移量紧跟在ModR/M字节之后。mod=10:带16位位移量寻址。所有r/m取值都对应「基址/变址寄存器 + 16位位移」的有效地址计算方式,比如r/m=110对应[BP+disp16],r/m=000对应[BX+SI+disp16],16位位移量以小端序紧跟在ModR/M字节之后。mod=11:寄存器直接寻址,此时r/m字段的编码规则和reg字段完全一致,直接映射对应寄存器,不产生内存访问。
补充提示:段寄存器不会通过ModR/M的reg/r/m字段编码,段切换是独立的指令前缀字节,不要和通用寄存器编码规则混淆。
内容的提问来源于stack exchange,提问作者Mauser_Maschine

