缘起:这阵子对动态解析比较感兴趣,对于动态解释型语言来说,这毫无研究的必要,但对于编译型的语言(主要讨论C/C++),凭着本人目前的水平,还
无法想出办法。想法是很简单的,例如,类似这样的win32函数 BOOL Beep(DWORD dwFreq,DWORD dwDuration),静态调用就不说了,动态调用的话,
先是LoadLibrary,然后取得Beep函数的地址,然后去invoke,但是,在编译期,必须显式地给出Beep的函数指针原型才能通过编译,因此,如果想偷懒,
不想给出原型以期达到广泛应用的话,至少现在微软提供的工具是没办法让你编译过的,那么怎么办呢? 比如我就想通过输入 函数名,参数1,参数1类型,
参数2,参数2类型...这样的字符串,然后我就优哉游哉的让程序自己去调用我想调用的函数,那怎么办呢?
思考:我们可以思考下微软自己是怎么实现动态链接和加载的呢,首先是加载库,然后取得函数地址,既然我们能得到函数的地址了,那我们就直接call呗,
嗯还得传参,这够麻烦的了,如果不传参的话,就没这么难了。没关系,我们看看函数的调用规则吧,压栈基址指针,基址指向栈顶,参数进栈,调用,
保存返回值,栈顶指向基址,出栈基址指针。那么,我们自己不也可以模拟下这个过程么?嗯,那就试试看吧
源码如下(win32下的console程序,vs2008下,vc++9.0 编译运行)
#include
#include
int main()
{
//加载函数库
HMODULE hMod = LoadLibraryA("Kernel32.dll");
//取得函数地址
FARPROC pfAddr = GetProcAddress(hMod,"Beep");
DWORD nRet ;//返回值
DWORD dwFreq = 750; //频率
DWORD dwDuration = 300;//持续时间
__asm
{
//注意调用方式,这是stdcall
push dwDuration//参数压栈,持续时间300毫秒
push dwFreq //继续压,频率
//...直到参数全部入栈
call pfAddr //开始调用
mov nRet,eax //取得回值
}
printf("%d",nRet);//输出返回值
//释放函数库
FreeLibrary(hMod);
return 0;
}
凭着"半拉可及"(俺们东北话)的知识,这个程序居然跑起来了,还不错,嗯,不过还得继续,因为我们忽略了我们想达到的目的中的一些细节,例如传参也要动态的,
不光是函数名,还有类型,不能光是int吧?不过这是个好的开端,因为内嵌的汇编可以做循环嘛,可以实现循环的压栈(根据参数个数), 也可以根据参数类型选择
相应的操作指令嘛,那就下次继续吧!
阅读(2338) | 评论(0) | 转发(0) |