WEB开发网
开发学院软件开发汇编语言 汇编教程之动态链接库 阅读

汇编教程之动态链接库

 2008-04-28 09:32:03 来源:WEB开发网   
核心提示:上面是一个动态链接库的框架,每一个DLL必须有一个入口点函数,汇编教程之动态链接库(2),WINDOWS每一次在做下面的动作时会调用该入口点函数:当动态链接库被加载时当动态链接库卸载时同一进程的线程生成时同一进程的线程退出时DllEntry proc hInstDLL:HINSTANCE, reason:DWORD,

上面是一个动态链接库的框架,每一个DLL必须有一个入口点函数,WINDOWS每一次在做下面的动作时会调用该入口点函数:

当动态链接库被加载时

当动态链接库卸载时

同一进程的线程生成时

同一进程的线程退出时

DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD

mov eax,TRUE

ret

DllEntry Endp

入口点函数的名称无所谓只要您让语句“END<函数名>”中的函数名和前面的相同就可以了。该函数共有三个参数,只有前面两个是重要的。

hInstDLL是该动态链接库模块的句柄。它和进程的实例句柄不一样。如果您以后要用,可以保存它,因为以后再要获得它不容易。

根据不同的时机,reason传入的值可能是下面的四个值中的一个:

DLL_PROCESS_ATTACH 动态链接库第一次插入进程的地址空间时。当传入的参数是该值时,您可以做一些初始化的工作。

DLL_PROCESS_DETACH 动态链接库从进程的地址空间卸出时。您可以在此做一些清理的工作。譬如:释放内存等。

DLL_THREAD_ATTACH 新线程生成。

DLL_THREAD_DETACH 线程销毁。

如果想要库中的代码继续执行,返回TRUE,否则返回FALSE,那样动态链接库就不会加载了。譬如:您想分配一块内存,如果不成功的话就退出,这时您就可以返回FALSE。那样动态链接库就不会加载了。

您可以加入的函数,它们的位置并不重要,把它们放在入口点函数的前面或后面都可以。只是如果您想要它们能被其它的程序调用的话,就必须把它们的名字放到模块定义文件(.def)中去。

动态链接库在它们自己的编译过程就需要,而不只是提供给其它要引用它的程序参考。他们如下:

LIBRARY DLLSkeleton

EXPORTS TestFunction

第一行是必须的。LIBRARY 定义了DLL的模块名称。它必须和动态链接库的名称相同。

EXPORTS关键字告诉链接器该DLL的引出函数,也就是其它程序可以调用的函数。举个例子:其它的程序想要调用函数TestFunction ,我们就把它放到EXPORTS中。

还有就是,链接器的选项中必须放入开关项:/DLL 和/DEF<DLL文件名>,就像下面这样:

link /DLL /SUBSYSTEM:WINDOWS /DEF:DLLSkeleton.def /LIBPATH:c:\masm32\lib DLLSkeleton.obj

编译器的开关选项是一样的,即:/c /coff /Cp。在您链接好后,链接器会生成.lib 和.dll文件。前者是引入库,当其它的程序要调用您的动态链接库中的函数时就需要该引入库,以便把必要的信息加入到其可执行文件中去。

接下来我们来看看如何使用LoadLibrary函数来加载一个DLL。

;---------------------------------------------------------------------------------------------
; UseDLL.asm
;----------------------------------------------------------------------------------------------
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.data
LibName db "DLLSkeleton.dll",0
FunctionName db "TestHello",0
DllNotFound db "Cannot load library",0
AppName db "Load Library",0
FunctionNotFound db "TestHello function not found",0
.data?
hLib dd ? ; 动态链接库的句柄 (DLL)
TestHelloAddr dd ? ; TestHello 函数的地址
.code
start:
invoke LoadLibrary,addr LibName
;---------------------------------------------------------------------------------------------------------
; 调用LoadLibrary,其参数是欲加载的动态链接库的名称。如果调用成功,将返回该DLL的句柄。 否则返回NULL。该句柄可以传给 :library函数和其它需要动态链接库句柄的函数。
;-----------------------------------------------------------------------------------------------------------
.if eax==NULL
invoke MessageBox,NULL,addr DllNotFound,addr AppName,MB_OK
.else
mov hLib,eax
invoke GetProcAddress,hLib,addr FunctionName
;-----------------------------------------------------------------------------------------------------------
; 当您得到了动态链接库的句柄后,把它传给GetProcAddress函数,再把您要调用的函数的名称 也传给该函数。如果成功的话,它:会返回想要的函数的地址,失败的话返回NULL。除非卸载该 动态链接库否则函数的地址是不会改变的,所以您可以把它保存到一个:全局变量中以备后用。
;-----------------------------------------------------------------------------------------------------------
.if eax==NULL
invoke MessageBox,NULL,addr FunctionNotFound,addr AppName,MB_OK
.else
mov TestHelloAddr,eax
call [TestHelloAddr]
;-----------------------------------------------------------------------------------------------------------
; 以后您就可以和调用其它函数一样调用该函数了。其中要把包含函数地址信息的变量用方括号括起来。
;-----------------------------------------------------------------------------------------------------------
.endif
invoke FreeLibrary,hLib
;-----------------------------------------------------------------------------------------------------------
;调用FreeLibrary卸载动态链接库。
;-----------------------------------------------------------------------------------------------------------
.endif
invoke ExitProcess,NULL
end start

使用LoadLibrary函数加载动态链接库,可能要自己多做一些工作,但是这种方法确实是提供了许多的灵活性。

上一页  1 2 

Tags:汇编 教程 动态

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接