Chinaunix首页 | 论坛 | 博客
  • 博客访问: 145809
  • 博文数量: 17
  • 博客积分: 2146
  • 博客等级: 大尉
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-07 23:26
文章分类

全部博文(17)

文章存档

2011年(1)

2009年(5)

2008年(11)

分类: WINDOWS

2009-09-06 21:33:20

缘起:这阵子对动态解析比较感兴趣,对于动态解释型语言来说,这毫无研究的必要,但对于编译型的语言(主要讨论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吧?不过这是个好的开端,因为内嵌的汇编可以做循环嘛,可以实现循环的压栈(根据参数个数), 也可以根据参数类型选择
相应的操作指令嘛,那就下次继续吧!

 
阅读(2307) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~