调函数的一个通用函数。还没有看很明白,fn为函数地址,args为参数(func(int param, ...),直接传¶m就可以了),argc为参数个数,(32位机4字节为一个), optr为this指针(VC 的 __thiscall),flags为标志(下面有定义,__cdecl不用清堆栈,QWORD好像是返回8字节内容,其它的没有看明白,好像与GCC有关。buff是返回值保存的地方。从C++解释器underC源码中取出来的。这个用来调用DLL中的函数比较爽的,不用声明原型,直接调用。
typedef int (*CALLFN)();
const int DC_CDECL = 1, DC_QWORD = 2, DC_NOWORD = 4, DC_RET_OBJ = 8, DC_RET_VAL = 16 + 8;
void *gObjectReturnPtr = NULL;
void callfn(CALLFN fn, int args[], int argc, void *optr, int flags, void *buff)
{
int sz = sizeof(int)*argc;
__asm {
mov ecx, argc
mov ebx, args
// push the arguments onto the stack, backwards
a_loop:
cmp ecx,0
jz a_out
mov eax, [ebx + 4*ecx]
push eax
dec ecx
jmp a_loop
a_out:
mov ecx,optr // thiscall calling convention (MS only)
call fn
// Cleanup stack ptr if this was a cdecl call
mov ecx, flags
test ecx,DC_CDECL
jz a_over
add esp,sz
a_over:
test ecx,DC_RET_OBJ
jz a_again
// these cases are peculiar to GCC
cmp ecx,DC_RET_VAL
jl a_skip
mov ebx, gObjectReturnPtr
mov [ebx],eax
mov [ebx+4],edx
jmp a_finish
a_skip:
sub esp,4
a_again:
mov ebx,buff
test ecx,DC_QWORD
jnz a_dbl
mov dword ptr[ebx],eax
jmp a_finish
a_dbl:
fstp qword ptr[ebx]
a_finish:
}
}
__int64 addi8(__int64 i1, __int64 i2)
{
return i1 + i2;
}
__int64 call(const char *name, const char *func, int nargs, ...)
{
union CalRet {
__int64 ret;
char sret[8];
} ret;
HMODULE h;
h = LoadLibrary(name);
void *addr = (void*)GetProcAddress(h, func);
int flag = DC_CDECL;
void *optr = NULL;
char buff[8];
ret.ret = 0;
callfn(addr, (int*)&nargs, nargs, optr, flag, ret.sret);
printf("ret %I64d/n", ret.ret);
FreeLibrary(h);
return ret.ret;
}
__int64 call(void *func, int nargs, ...)
{
union CalRet {
__int64 ret;
char sret[8];
} ret;
int flag = DC_CDECL|DC_QWORD;
void *optr = NULL;
char buff[8];
ret.ret = 0;
callfn(func, (int*)&nargs, nargs, optr, flag, ret.sret);
printf("ret %I64u/n", ret.ret);
return ret.ret;
}
int main(int argc, char* argv[])
{
char *s = "Hello, %s, %d/n";
char *s1 = "GOGO";
int i = 32;
setlocale(LC_ALL, ".936");
call("msvcrt.dll", "wprintf", 2, L"Hello, %s/n", L"abc");
call(addi8, 4, (unsigned __int64)-1, 0I64);
return 0;
}