文件是否是动态链接库取决于它的文件结构,动态链接库和可执行文件同样使用标准的PE文件格式,公文件头中的属性位不同而以,所以EXE中的一些特征也存在于动态链接库中,比如,可以定义并使用各种资源,可以导入并使用其他动态链接库中的函数等.
要牢记一个概念:动态链接库是被映射到其他应用程序的地址空间中执行的,它和应用程序可以看成是"一体"的,动态链接库可以使用应用程序的资源,它所拥有的资源也可以被应用程序使用,它的任何操作都是代表应用程序进行的,当动态链接库进行打开文件,分配内存和创建窗口等操作后,这些文件,内存和窗口都是为应用程序所拥有的.
例:(罗老板的代码)
Dll.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Sample.asm
; Link /subsystem:windows /Dll /Def:Sample.def Sample.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?dwCounter dd ?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的入口函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DllEntry proc _hInstance,_dwReason,_dwReservedmov eax,TRUE
retDllEntry Endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 本函数在 dll 内部使用
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CheckCounter procmov eax,dwCounter
cmp eax,0
jge @F
xor eax,eax
@@:
cmp eax,10
jle @F
mov eax,10
@@:
mov dwCounter,eax
ret_CheckCounter endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的导出函数之一
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_IncCounter procinc dwCounter
call _CheckCounter
ret_IncCounter endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的导出函数之二
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_DecCounter procdec dwCounter
call _CheckCounter
ret_DecCounter endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的导出函数之三
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Mod proc uses ecx edx _dwNumber1,_dwNumber2xor edx,edx
mov eax,_dwNumber1
mov ecx,_dwNumber2
.if ecx
div ecx
mov eax,edx
.endif
ret_Mod endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
End DllEntry
程序仅定义了5个子程序,其中程序的入口由最后一句End定义到了DllEntry处.
程序入口代码什么都没做,仅返回一个TRUE,也没有用到_IncCounter,_DecCounter,_Mod函数,这是因为DLL文件被设计为不是供自己使用的,而是被映射到其他应用程序的地址空间中代表"宿主"程序执行的,这些函数就是供其他程序使用的函数,这些函数对于宿主来说和User32.dll中的CreateWindowEx等极其复杂的函数没有任何区别
1.入口点和初始化代码
DllEntry proc hInstDll,dwReason,dwReserved
mov eax,dwReason
.if eax == DLL_PROCESS_ATTACH
;保存hInstDll
;初始化库需要的各种资源.if 初始化成功
mov eax,TRUE
.else
mov eax,FALSE
.endif
.elseif eax == DLL_THREAD_ATTACH
;为新的线程分配资源
.elseif eax == DLL_THREAD_DETACH
;为线程释放资源
.elseif eax == DLL_PROCESS_DETACH
;释放库使用的资源
.endif
retDllEntry Endp
动态链接库需要一个入口点,这个入口点是一个函数,函数
名并不重要,例子中函数名为DllEntry,可以把它取名为任何合法的名字,但入口函数的格式是有规定的.库的入口函数对调用动态链接库的应用程序来说是不可见的,它仅供操作系统使用.windows在库加载,卸载,进程中线程的创建和结束等时候调用入口函数,以便动态链接库采取相应的动作.在入口函数中可以通过参数来判别本次调用究竟是在哪种情况下发生的.
Windows会传给入口函数3个参数
dwReason:表示本次调用的原国,可能是四种情况之一
DLL_PROCESS_ATTACH:表示动态链接库刚被映射到进程的地址空间,程序可以在这里进行一些初始化的工作,成功返回TRUE,失败返回FALSE.这给了动态链接库一个机会来阻止自己被装入.比如库可以在这里申请并保留一些内存,如果申请失败的话返回FALSE告诉windows,库无法正常工作.