x86架构m*操作数(含FPU)解析疑问:32位反汇编开发困惑
关于x86反汇编器开发中操作数符号的困惑解答
嘿,我太懂你这种对着Intel手册一头雾水的感觉了——当初我啃手册写第一个简易反汇编器的时候,也在这些操作数符号上卡了好几天!咱们一步步拆解你的问题:
一、m8/m16/m32和ES:(E)DI/DS:(E)SI的适用场景
首先要明确:m8/m16/m32是内存操作数的通用符号,指代任意可寻址的内存字节/字/双字。而ES:(E)DI、DS:(E)SI是它的特殊绑定变体,只在字符串操作指令里生效:
- 当你看到手册里字符串指令(比如
LODS、STOS、MOVS、CMPS这类)标注的m8,它就不是随便的内存地址了:LODS m8:这里的m8固定对应DS:(E)SI指向的内存单元,指令会把这个字节加载到AL寄存器STOS m8:这里的m8固定对应ES:(E)DI指向的内存单元,指令会把AL的值写入这个内存地址MOVS m8:同时用到两个——源是DS:(E)SI,目的是ES:(E)DI
- 而普通指令(比如
INC m8、ADD m8, r8)里的m8,就是你常规理解的任意内存地址(比如[eax]、[0x401000]、[ebp-4]这类),和那两个寄存器完全没关系。
二、操作码的单/双m8操作数规则
操作数的数量完全取决于指令的功能设计,没有绝对的通用规则,但可以分两类记:
1. 单操作数指令
这类指令只需要一个操作对象,要么是对内存单元做单目运算,要么是隐含了另一个操作数:
- 单目运算类:比如
INC m8(内存字节自增)、NOT m8(内存字节按位取反)、NEG m8(内存字节取负),这类指令只需要指定要操作的内存位置,所以手册里只写一个m8 - 隐含操作数类:还是字符串指令,比如
STOS m8看起来只有一个m8,但实际隐含了另一个操作数AL(把AL的值写到m8指向的内存),只是手册没把隐含操作数写在显式格式里
2. 双操作数指令
这类指令需要明确源和目的操作数(注意:x86里大部分双操作数指令不支持内存到内存的直接操作,比如MOV m8, m8是非法的,必须通过寄存器中转):
- 比如
ADD m8, r8:把寄存器r8的值加到m8指向的内存字节里,结果存在内存 - 比如
CMP m8, r8:比较内存字节和寄存器字节,结果反映在标志位里 - 这类指令的手册格式会写出两个操作数,明确谁是源谁是目的(注意顺序:x86手册里一般是「目的, 源」的顺序)
实用小技巧
如果你还是拿不准,直接看Intel手册里的「Instruction Operand Encoding」部分:
- 这里会用编码代号(比如
ModRM、Immediate)告诉你操作数是怎么编码的,哪些是隐含寄存器,哪些需要显式指定 - 比如字符串指令的Operand Encoding里,会明确标注
DS:(E)SI或ES:(E)DI是隐含的,不用通过ModRM字节编码
内容的提问来源于stack exchange,提问作者TrisT
相关产品推荐
相关产品推荐

