动态链接库 - 编写

文件是否是动态链接库取决于它的文件结构,动态链接库和可执行文件同样使用标准的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,_dwReserved

    mov  eax,TRUE
    ret

DllEntry  Endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 本函数在 dll 内部使用
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CheckCounter  proc

    mov  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  proc

    inc  dwCounter
    call  _CheckCounter
    ret

_IncCounter  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的导出函数之二
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_DecCounter  proc

    dec  dwCounter
    call  _CheckCounter
    ret

_DecCounter  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的导出函数之三
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Mod    proc  uses ecx edx _dwNumber1,_dwNumber2

    xor  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
    ret

DllEntry    Endp

动态链接库需要一个入口点,这个入口点是一个函数,函数

名并不重要,例子中函数名为DllEntry,可以把它取名为任何合法的名字,但入口函数的格式是有规定的.库的入口函数对调用动态链接库的应用程序来说是不可见的,它仅供操作系统使用.windows在库加载,卸载,进程中线程的创建和结束等时候调用入口函数,以便动态链接库采取相应的动作.在入口函数中可以通过参数来判别本次调用究竟是在哪种情况下发生的.

Windows会传给入口函数3个参数
dwReason:表示本次调用的原国,可能是四种情况之一
DLL_PROCESS_ATTACH:表示动态链接库刚被映射到进程的地址空间,程序可以在这里进行一些初始化的工作,成功返回TRUE,失败返回FALSE.这给了动态链接库一个机会来阻止自己被装入.比如库可以在这里申请并保留一些内存,如果申请失败的话返回FALSE告诉windows,库无法正常工作.

动态链接库 - 编写》有一个想法

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注