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

x64 MASM中获取C++函数第5、6个参数及栈帧相关疑问

x64 MASM 栈参数布局与寄存器解析(基于你的示例)

先修正你写的汇编代码——你的代码错误地读取了影子空间和多余的栈数据,正确实现应该是这样:

.code
AddAsm proc
    mov rax, rcx    ; 取第1个参数a=1
    add rax, rdx    ; 加第2个参数b=2 → 3
    add rax, r8     ; 加第3个参数c=3 → 6
    add rax, r9     ; 加第4个参数d=4 → 10
    add rax, qword ptr [rsp+40] ; 加第5个参数e=5 → 15
    add rax, qword ptr [rsp+48] ; 加第6个参数f=6 → 21
    ret
AddAsm endp
end

下面结合你的示例拆解核心问题:

1. Windows x64调用约定的栈布局(函数刚进入时)

当main调用AddAsm(1,2,3,4,5,6)时,调用者会先完成以下栈操作:

  • 预留32字节的影子空间(用于备份前4个寄存器参数,调用者必须分配,不管函数是否使用)
  • 从右往左压入剩余参数:先压f=6,再压e=5
  • 执行call AddAsm,此时返回地址(8字节)被压入栈

进入AddAsm后,rsp指向返回地址,栈的具体布局如下(偏移以rsp为基准):

偏移内容值
0返回地址(8字节)——
+8影子空间第1位(rcx备份)1
+16影子空间第2位(rdx备份)2
+24影子空间第3位(r8备份)3
+32影子空间第4位(r9备份)4
+40第5个参数e(8字节)5
+48第6个参数f(8字节)6

你之前的代码错误地读取了影子空间的rsp+32(对应d的备份,已经在r9里),还多取了rsp+56的垃圾数据,这会导致结果错误。

2. rsp与rbp的含义

  • rsp:栈指针:始终指向栈顶(x64栈向下增长,push会让rsp减小,pop会让rsp增大)。因为rsp会随栈操作动态变化,直接用它访问参数时要注意偏移的准确性。
  • rbp:基指针:作为栈帧的固定基准,方便访问局部变量和参数。如果要用rbp,需要手动保存旧rbp并设置新的栈帧:
    .code
    AddAsm proc
        push rbp        ; 把旧rbp压栈保存
        mov rbp, rsp    ; 让rbp指向当前栈顶(旧rbp的位置)
        
        ; 此时用rbp访问参数:
        mov rax, rcx
        add rax, rdx
        add rax, r8
        add rax, r9
        add rax, qword ptr [rbp+48] ; e=5(rbp+8是返回地址,+16到+40是影子空间)
        add rax, qword ptr [rbp+56] ; f=6
        
        pop rbp         ; 恢复旧rbp
        ret
    AddAsm endp
    end
    

3. 参数偏移的规律

  • 前4个参数固定用rcx/rdx/r8/r9传递
  • 第5个及以后的参数,在函数刚进入时,从rsp+40开始,每个参数占8字节(x64栈强制8字节对齐,即使是int类型也会被零扩展为8字节存储)
  • 如果用rbp作为基准,第5个参数的偏移是rbp+48,后续每个参数偏移+8

内容的提问来源于stack exchange,提问作者Jacob Krieg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:47:10