如何在C#中调用x64汇编过程 直接及C++间接调用问题咨询
问题1解答
C# 可以直接调用MASM编译生成的DLL,你之前调用抛出二进制不兼容异常通常是以下原因导致:
- 项目架构不统一:比如C#项目设置为Any CPU,而ASM DLL编译为x86/x64单架构,或者两边架构完全不匹配
- 调用约定不匹配:C#的
DllImport默认调用约定是StdCall,若ASM导出函数使用其他调用约定且没有显式声明就会报错 - 导出函数名不匹配:未使用def文件或者声明导出规范,导致MASM编译时对函数名做了修饰,C#找不到对应入口
问题2解答
你返回随机值的核心原因是调用约定不匹配,具体问题出在:
你在C++中定义的函数指针是__stdcall类型,但是你的ASM代码既没有指定调用约定,也没有按照__stdcall的规则清理栈:
__stdcall要求被调用方负责清理参数栈,你传入两个DWORD参数共8字节,ASM的ret指令需要手动释放这部分栈空间- 你当前ASM的实现默认使用
CDECL调用约定,由调用方清理栈,C++用__stdcall去调用的话会导致栈不平衡,返回值读取异常
修复方案二选一即可:
方案1:修改ASM代码适配__stdcall约定
你的Main.asm代码调整为:
.386 .model flat, stdcall .stack 4096 MyProc1 proc x: DWORD, y: DWORD mov EAX, x mov ECX, y add EAX, ECX ret 8 ; 两个DWORD参数共8字节,被调用方清理栈 MyProc1 endp end
同时确保你的def文件导出名正确,ASM项目编译架构和C++、C#项目统一。
方案2:修改C++的函数指针约定为CDECL匹配ASM默认实现
将C++中的函数指针定义修改为:
typedef int(__cdecl* f_MyProc1)(DWORD, DWORD);
不需要修改ASM代码即可正常运行。
额外说明
如果要直接在C#中调用ASM DLL,只要保证导出函数名正确、调用约定匹配、架构统一即可,不需要经过C++中转,示例代码:
// 对应__stdcall约定的ASM函数 [DllImport("Algorithm.Asm.dll", CallingConvention = CallingConvention.StdCall)] public static extern int MyProc1(int x, int y);
内容的提问来源于stack exchange,提问作者nooblet
相关产品推荐
相关产品推荐

