直接调用函数的函数

来源:互联网 发布:单片机控制电磁阀电路 编辑:程序博客网 时间:2024/04/30 07:15

 

调函数的一个通用函数。还没有看很明白,fn为函数地址,args为参数(func(int param, ...),直接传&param就可以了),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;

}

 

 

原创粉丝点击