如何在C++中像C一样声明带动态参数的汇编函数
C++中调用带可变参数的汇编函数问题解决
问题说明
将C代码移植到C时,调用一个位于单独asm文件、用于直接调用ntdll.dll系统调用的汇编函数时出现编译错误。C中无参数列表的函数声明默认支持可变参数,可正常调用;但C中extern "C" VOID asmFunc();的声明会严格检查参数数量,导致传入多参数时触发E0140 too many arguments in function call错误。
C版本正常代码
extern asmFunc(); // C中无参数列表的声明默认允许可变参数 // 调用示例 asmFunc(var1, ptr2, HANDLE); asmFunc(ptr4, var2, NULL, eg ...); // 正常运行
C++版本报错代码
extern "C" VOID asmFunc(); // C++中此声明表示函数无参数 // 调用示例 asmFunc(var1, ptr2, HANDLE); // 编译错误:E0140 参数过多 asmFunc(ptr4, var2, NULL, eg ...); // 编译错误:E0140 参数过多
解决方法
1. 修改函数声明为可变参数形式
直接将C++中的函数声明改为支持可变参数的写法,同时保留extern "C"确保C调用约定:
extern "C" void asmFunc(...);
这样编译器会允许传入任意数量的参数,行为和C中的声明完全一致。
2. 使用函数指针兼容
如果无法修改原始声明,可以通过函数指针来绕过参数检查:
// 定义支持可变参数的函数指针类型 typedef void (*AsmFuncPtr)(...); // 关联到目标函数 extern "C" void asmFunc(); AsmFuncPtr funcPtr = reinterpret_cast<AsmFuncPtr>(&asmFunc); // 通过指针调用,支持可变参数 funcPtr(var1, ptr2, HANDLE); funcPtr(ptr4, var2, NULL, eg ...);
3. 确认并匹配调用约定
确保汇编函数使用支持可变参数的调用约定(如cdecl,该约定由调用者负责清理栈,适配可变参数场景):
- C++声明明确指定调用约定:
extern "C" void __cdecl asmFunc(...); - 汇编文件中对应设置调用约定(以MASM为例):
PUBLIC _asmFunc _asmFunc PROC C ; C代表cdecl调用约定 ; 汇编实现逻辑 _asmFunc ENDP
内容的提问来源于stack exchange,提问作者user16658873
相关产品推荐
相关产品推荐

