如何在x64汇编中基于局部变量进行偏移寻址?
问题
我想要访问当前栈帧中的第二个局部变量,我认为它位于%rsp-8的位置(第一个局部变量在%rsp)。我需要将%rsp-8这个地址本身加载到另一个寄存器中(注意不是该地址对应内存里存储的数据)。请问能否无需使用单独寄存器存储偏移、也不修改当前%rsp的前提下实现这一操作?
当前代码:
... movq %rsp, %rsi # 将rsp处的第一个地址移入rsi leaq infmt, %rdi # 将输入格式字符串加载到rdi movq $0, %rax # 清空rax,因为这是可变参数函数 call scanf movq %rsp, %rbx addq $8, %rbx movq %rbx, %rsi # 将rsp处的下一个地址移入rsi leaq infmt, %rdi # 重新加载输入格式 call scanf ...
我期望的简化写法(注:以下写法语法错误,仅为示意):
... movq %rsp, %rsi # 将rsp处的第一个地址移入rsi leaq infmt, %rdi # 将输入格式字符串加载到rdi movq $0, %rax # 清空rax,因为这是可变参数函数 call scanf movq %rbx-8, %rsi # 将rsp-8处的地址移入rsi(语法错误) leaq infmt, %rdi # 重新加载输入格式 call scanf ...
解答
完全可以实现,你需要用leaq(Load Effective Address)指令来完成这个需求:
leaq的作用是计算内存操作数的有效地址,并将这个地址值直接加载到目标寄存器中,不会实际访问内存,正好符合你要获取%rsp-8地址本身的需求。
替换你期望代码中的错误行,正确的指令是:
leaq -8(%rsp), %rsi
修改后的完整代码如下:
... movq %rsp, %rsi # 将rsp处的第一个地址移入rsi leaq infmt, %rdi # 将输入格式字符串加载到rdi movq $0, %rax # 清空rax,因为这是可变参数函数 call scanf leaq -8(%rsp), %rsi # 将rsp-8的地址直接移入rsi leaq infmt, %rdi # 重新加载输入格式 call scanf ...
你原来的期望写法行不通的原因是:x86-64汇编中,movq不支持直接对寄存器做算术运算后赋值的语法(比如%rbx-8这种写法是非法的);而且就算语法允许,你要的是地址偏移后的地址值,leaq才是专门处理地址计算的指令,movq更多用于数据移动或内存加载。
内容的提问来源于stack exchange,提问作者TheSinisterStone
相关产品推荐
相关产品推荐

