C++与汇编混合编程:无法从C++函数向汇编传递多个参数
解决x64下C++调用汇编函数的参数传递问题
我来帮你搞定这个参数传递的坑!你的问题核心是没搞清楚Microsoft x64调用约定的规则,这是VS2017 x64环境下默认遵循的函数调用规范。
问题原因
在x64平台上,C++和MASM默认遵循的调用约定是:前4个整型/指针参数会通过寄存器依次传递(RCX→第一个参数,RDX→第二个参数,R8→第三个,R9→第四个),剩下的参数才会放到栈上。而你用MASM的PROC声明参数后,错误地直接通过参数名去读取,却没有处理栈的影子空间和对齐要求,导致第二个参数读取到了无效的栈内存值。
解决方案1:直接使用寄存器获取参数(最简单)
既然前两个参数已经在寄存器里了,直接用RCX和RDX就能拿到正确的地址,不需要依赖PROC的参数名:
.code set_clock PROC ; 分配32字节的影子空间(保证栈16字节对齐,调用其他函数时也需要这个空间) sub rsp, 32 ; 第一个参数:clock的地址 → 存在RCX中 mov rsi, rcx ; 把clock地址存入rsi(你原来用rdx也可以,这里换rsi只是示例) ; 第二个参数:localTime的地址 → 存在RDX中 mov rdi, rdx ; 执行你的操作:取clock第一个字节,写入localTime mov al, [rsi] mov [rdi], al ; 释放影子空间 add rsp, 32 ret set_clock ENDP END
解决方案2:正确使用MASM的PROC参数声明
如果你想保留参数名的可读性,需要先分配影子空间,让MASM能正确把寄存器里的参数映射到栈的影子空间中:
.code set_clock PROC, pClock:QWORD, pTimeInfo:QWORD ; 分配32字节影子空间(满足栈对齐,同时让参数名对应到正确的栈位置) sub rsp, 32 ; 现在可以直接用参数名访问,MASM会自动处理从寄存器/影子空间读取 mov rsi, pClock ; pClock对应第一个参数(RCX) mov rdi, pTimeInfo ; pTimeInfo对应第二个参数(RDX) mov al, [rsi] mov [rdi], al add rsp, 32 ret set_clock ENDP END
关键注意点
- 栈对齐:x64要求栈指针
RSP必须始终保持16字节对齐。调用CALL指令后,RSP会减8(存储返回地址),所以进入函数后必须通过sub rsp, 8n(n为整数)让RSP回到16字节对齐状态。 - 影子空间:调用者会在调用函数前分配32字节的影子空间,被调用者可以用这个空间保存
RCX/RDX/R8/R9的值,避免后续调用其他函数时寄存器被覆盖。即使你不调用其他函数,分配影子空间也是符合规范的做法。
这样修改后,第二个参数就能正确拿到localTime的地址,内存访问错误也会消失啦!
内容的提问来源于stack exchange,提问作者I Like
相关产品推荐
相关产品推荐

