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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:35:22