Win32内联汇编调用带参函数问题解决与自定义FFI接口实现
基于汇编实现自定义FFI接口(修复__stdcall函数调用栈崩溃问题)
问题背景
需要调用a1.dll中导出的__declspec( dllexport ) int i32(int y)函数(调用约定为__stdcall),最初通过手动汇编压栈传递参数时程序崩溃,现已定位并修复问题,以下是完整实现方案。
错误原因分析
原汇编代码中在函数调用后执行了pop %%eax操作,而__stdcall约定要求被调用者负责清理栈(函数返回时会执行ret n指令,n为参数总字节数),手动弹出参数会破坏栈平衡,导致程序崩溃。
修正后的完整代码
#include <stdio.h> #include <windows.h> struct prot{ void* retn; void* arg1; void* arg2; void* arg3; void* arg4; int arg_len; }; typedef struct prot Prot; void c_func(void* fun, Prot* p){ __asm__( "mov %2, %%eax\n\t" "push %%eax\n\t" // 按__stdcall约定压入参数(从右到左,此处仅一个参数) "mov %1, %%eax\n\t" "call *%%eax\n\t" // 调用目标函数 "mov %%eax, %0\n\t" // __stdcall约定返回值存于eax,保存到结构体的retn字段 : "=r"(p->retn) : "r" (fun), "r"(p->arg1) : "%eax" ); } typedef int(__stdcall *fp)(int); int main(){ HMODULE hDll = LoadLibrary("a1.dll"); fp lpFunc = (fp)GetProcAddress(hDll, "i32"); Prot p; p.arg1 = (void*)35; p.arg_len = 1; c_func(lpFunc, &p); printf("retorno: %d\n", (int)p.retn); FreeLibrary(hDll); return 0; }
关键实现要点
- 调用约定适配:严格遵循__stdcall规则,由被调用者清理栈,调用者无需手动弹出参数
- 参数传递:x86架构下__stdcall要求参数从右到左压栈,单个参数直接压入即可,多参数场景需按逆序依次压栈
- 返回值处理:__stdcall约定下整数返回值存储在
eax寄存器,直接读取该寄存器值保存即可 - 扩展性设计:
Prot结构体支持最多4个参数存储,arg_len标记实际参数数量,便于后续扩展多参数函数调用
内容的提问来源于stack exchange,提问作者Rlc888
相关产品推荐
相关产品推荐

