You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于x64中ModR/M历史符号/0.../7的技术咨询

x64架构中MOV指令编码相关疑问解答

我在学习x64架构时,对Intel手册里的部分符号存在理解困惑,以0xC7对应的MOV指令为例,其指令编码如下:

opcodeinstructionOp/Enc说明
C7 /0 iwMOV r/m16, imm16MI将imm16移动到r/m16。
C7 /0 idMOV r/m32, imm32MI将imm32移动到r/m32。
REX.W + C7 /0 idMOV r/m64, imm32MI将imm32符号扩展为64位后移动到r/m64。

手册中关于/0../7符号的说明:

历史上,本文档仅使用/0.../7符号指定ModR/M.reg字段的限制,并未在编码框中指定ModR/M.mod和ModR/M.r/m字段的限制。

提出的技术问题

  1. /0后的数字是限制码,具体代表何种限制?在解读指令时它的含义是什么?
  2. 当读取如c7c701020304...这类字节序列时,如何判断应读取imm16(0102)还是imm32(01020304)?经测试此处为imm32,但我不理解原因,推测与rex+modrm相关。
  3. 换而言之:为何ndisasm将该字节序列解析为imm32而非imm16?

测试代码及结果:

{ xxd --ps -r | ndisasm -b64 -; } <<<c7c701020304 
00000000  C7C701020304      mov edi,0x4030201

问题解答

1. /0的具体含义

/n(n取0-7)是Intel手册用来限定ModR/M字节中reg字段取值的符号。以C7 /0为例,它要求紧跟在0xC7后的ModR/M字节里,3位的reg字段二进制值必须是000(对应十进制0)。

ModR/M字节由mod(2位)、reg(3位)、r/m(3位)三个部分构成,/0只约束reg字段的值,mod和r/m字段可根据实际寻址需求变化——只要reg字段符合要求,这条指令就匹配C7 /0对应的MOV指令变种。

2. 区分imm16与imm32的判断逻辑

判断立即数长度的核心是当前操作数模式和指令对应的操作数宽度:

  • 你提供的字节序列是在64位模式下解析的(ndisasm指定了-b64参数),64位模式下默认操作数宽度为32位(除非有REX.W前缀显式指定64位操作数)。
  • 字节序列c7 c7 01020304中,第一个字节C7无REX前缀,匹配的是C7 /0 id(MOV r/m32, imm32)指令。第二个字节C7是ModR/M字节,它的reg字段为000(满足/0的要求),同时mod字段为11(寄存器寻址)、r/m字段为111,对应32位寄存器EDI(64位模式下无REX.W时,r/m=111指向EDI)。
  • 而MOV r/m16, imm16(C7 /0 iw)仅在16位操作数模式下生效,或需通过0x66前缀强制切换到16位模式才会被匹配,默认64位模式下不会优先选择该变种。

3. ndisasm解析为imm32的原因

ndisasm以64位模式解析时:

  1. 识别第一个字节C7,无REX前缀,对应C7 /0 id指令,该指令要求后续跟4字节的imm32。
  2. 第二个字节C7作为ModR/M字节,reg字段为000(符合/0的约束),确认匹配该指令变种。
  3. 因此ndisasm读取后续4字节作为imm32,解析为mov edi, 0x4030201;而16位变种需要额外的0x66前缀触发,当前字节序列中没有该前缀,所以不会被选中。

内容的提问来源于stack exchange,提问作者ton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:43:15