我使用以下类型在运行时创建一个新函数:
typedef int (*pfunc)(int);
union funcptr {
pfunc x;
byte* y;
};
这使我能够在 y
中编写指令,然后像这样调用函数:
byte* p = (byte*)VirtualAllocEx(GetCurrentProcess(), 0, 1<<16, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
// Write some instructions to p
funcptr func;
func.y = p;
int ret = func.x(arg1); // Call the generated function
了解 C++ 如何准备参数(调用约定)至关重要,因此我查看了项目属性 (Visual C++),我可以看到它使用 __cdecl
。它应该根据以下参数将参数放在堆栈上:http://msdn.microsoft.com/en-us/library/aa271989(v=vs.60).aspx和 http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl但是当我查看生成的程序集时,参数被移动到 EAX 寄存器。
我想绝对确定参数是如何准备的。那么我是不是忽略了一些关于 cdecl
的事情,或者 Visual C++ 是否优化了调用,如果是这样,我如何确保它不会发生?
最好的问候,Lasse Espeholt
最佳答案
EAX
寄存器是 used for the return value of the function .您在评论中声明您正在使用 /Gd
进行编译所以该函数将使用 __cdecl
.尽管如此,在我看来,用显式 __cdecl
标记函数类型 pfunc
的声明是有意义的,这样就不会出现混淆和不匹配的情况.
当然,没有什么可以阻止您使用您的编译器支持的其他调用约定之一。最重要的一点是,无论您选择哪种调用约定,都应该明确指定函数指针的调用约定,因为编译器只负责接口(interface)的一半。
关于c++ - (Visual) C++ 中动态创建函数的调用约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8279715/