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

x64汇编参数传递异常:为何参数通过RDI/R10/R11而非栈传递?

问题分析与解决

首先明确:Windows x64平台下只有一种官方调用约定(Microsoft x64 Calling Convention),不存在前4个参数用寄存器、剩余参数用RDI/R10/R11传递的规则。你遇到的问题是汇编代码的栈帧处理和参数偏移计算错误导致的,而非调用约定变更。

核心规则回顾(Windows x64调用约定)

对于整型/指针类型参数:

  • 前4个参数依次通过 RCX(第1个)、RDX(第2个)、R8(第3个)、R9(第4个)寄存器传递
  • 第5个及以后的参数,由调用者压入栈中,被调用者通过栈帧指针(RBP)的正偏移访问
  • 调用者会为前4个寄存器参数分配32字节的阴影空间(Shadow Space),位于栈上返回地址的下方

你的汇编代码错误点

  1. 栈帧初始化错误
    你用 sub rbp, 16 分配局部变量空间是错误的。正确的做法是在 mov rbp, rsp 之后,通过 sub rsp, 16 来分配局部变量(栈向下增长,需要将栈指针下移)。sub rbp,16 会破坏栈帧的偏移计算逻辑,导致后续无法正确定位栈上的参数。

  2. 参数偏移计算错误
    进入函数后,栈帧相对于 RBP 的布局(十进制偏移):

    • rbp+0:保存的旧 RBP
    • rbp+8:返回地址
    • rbp+16 ~ rbp+47:32字节阴影空间
    • rbp+48:第5个参数(resY)
    • rbp+56:第6个参数(alignment)
    • rbp+64:第7个参数(iterCount)
      你写的 [rbp+50o] 是八进制的40,对应阴影空间的位置,并非参数所在的栈地址,读取到的是无效数据。

修正后的汇编代码示例

.code
generateMandelMASM PROC
    ; 标准栈帧序言
    push rbp
    mov rbp, rsp
    ; 分配局部变量空间:2个变量(DWORD+QWORD)共12字节,对齐到16字节,所以sub rsp,16
    sub rsp, 16

    ; 读取参数示例
    ; 参数1: RCX → bmp数组指针
    ; 参数2: EDX → rowCount
    ; 参数3: R8D → rowNum
    ; 参数4: R9D → resX
    mov eax, dword ptr [rbp+48]   ; 读取第5个参数resY
    mov ecx, dword ptr [rbp+56]   ; 读取第6个参数alignment
    mov edx, dword ptr [rbp+64]   ; 读取第7个参数iterCount

    ; 保存到局部变量
    mov dword ptr [rbp-4], ecx    ; alignment(DWORD,占rbp-4到rbp-1)
    mov qword ptr [rbp-16], rdx   ; rowCount(QWORD,占rbp-16到rbp-9)

    ; 你的曼德博集合生成逻辑...

    ; 栈帧尾声
    mov rsp, rbp
    pop rbp
    ret
generateMandelMASM ENDP

额外说明

  • C#的 DllImport 在Windows x64下默认使用的就是官方调用约定,显式指定调用约定不会改变参数传递规则(x64平台不区分StdCall/Cdecl)。
  • 你调试时看到RDI/R10/R11中有参数值,是巧合或者调试环境的临时数据,并非调用约定的一部分。

内容的提问来源于stack exchange,提问作者mc jazda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:13:14