x86-64指令解码中默认操作数大小的确定:如何选择对应段的操作模式
x86-64指令解码中默认操作数大小的确定:如何选择对应段的操作模式
嘿,这个问题问到点子上了——我当初自己写x86-64指令解码工具的时候,也在这个坑上卡了好一会儿!
首先给你一个核心结论:绝大多数情况下,指令的默认操作数/地址大小,完全由当前执行代码所在的CS(代码段)的属性决定,和你要访问的数据所在的段(比如DS、ES、SS这些)没有关系。
下面给你拆解清楚:
- CPU的当前运行模式(64位长模式、32位兼容模式、16位实模式/虚拟8086模式),是由CS段描述符里的
CS.L(长模式位)、CS.D(默认操作数大小位),再加上EFER寄存器的LMA(长模式激活位)共同判定的。CPU执行任何指令时,都会基于这个当前模式来确定默认的操作数大小。 - 举个例子,就像你贴的这个
add指令的隐式操作数场景:
如果当前是64位长模式(CS.L=1且CS.D=0),默认操作数大小就是64位;如果是32位兼容模式(CS.L=0且CS.D=1),默认是32位;要是处于16位模式(CS.L=0且CS.D=0),默认就是16位。 - 操作数前缀的作用:如果指令编码里带有
0x66前缀,会翻转当前模式下的默认操作数大小——比如64位模式下默认64位,加0x66就变成32位;32位模式下默认32位,加0x66就变成16位,以此类推。 - 特殊情况补充:像字符串指令(比如
movsb、stosb这类),它们的操作数大小也是由CS段的CS.D位决定的,同样可以被0x66前缀修改,和数据段无关。
简单来说,你不需要去检查数据段的描述符属性,只需要聚焦当前执行代码所在的CS段的模式标识,就能准确判断指令的默认操作数大小了。
备注:内容来源于stack exchange,提问作者nick17
相关产品推荐
相关产品推荐

