x86汇编:基址索引模式转间接寻址(第二部分)——转换报错求助
问题分析与解决方法
嘿,我一眼就看出你哪里错了——addl $8, string这行根本不能这么写!
为什么原代码会报错?
string是一个编译时确定的符号地址,相当于一个固定的常量(比如链接后它可能是0x402000这种固定值)。你用addl指令试图修改这个常量地址本身,完全不符合汇编的规则:
- 符号地址是只读的,属于程序的静态数据/代码段,不能被算术指令直接修改;
addl的内存操作数要求是可写的内存单元,而string代表的是地址,不是可写的内存位置。
原指令movzbl string+8, %eax的实际作用是:直接访问string起始地址偏移8字节处的内存单元,把那个字节零扩展后加载到%eax里,这是直接寻址模式。
正确的简单间接寻址转换方法
如果要转换成寄存器间接寻址模式(也就是你说的“简单间接寻址”),你需要借助一个通用寄存器来保存偏移后的地址,再通过寄存器间接访问内存:
# 步骤1:把string的基地址加载到通用寄存器(比如%ebx) leal string, %ebx # 步骤2:给寄存器加上偏移量8 addl $8, %ebx # 步骤3:通过寄存器间接寻址读取内存,零扩展到%eax movzbl (%ebx), %eax
或者你也可以用movl先加载地址,再做加法,效果完全一致:
movl $string, %ebx addl $8, %ebx movzbl (%ebx), %eax
额外说明
如果你只是想简化寻址模式但不想用寄存器,其实movzbl string+8, %eax本身已经是很简洁的直接寻址了;不过如果你的需求必须用间接寻址,上面的方法就是标准的正确做法。
内容的提问来源于stack exchange,提问作者Biggy Poopa
相关产品推荐
相关产品推荐

