demoDll.asm
.386
.model flat,stdcall
option casemap:none
include windows.inc
.data
dwCounter dd ?
.code
_EntryDll proc _hInstance,_dwReason,_dwReserved
mov eax,TRUE
ret
_EntryDll endp
_CheckCounter proc;限制dwCounter的值为0-10
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
_incCounter proc
inc dwCounter
call _CheckCounter
ret
_incCounter endp
_decCounter proc
dec dwCounter
call _CheckCounter
ret
_decCounter endp
End _EntryDll
useDll1
.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
include demoDll.inc
includelib demoDll.lib
IDD_MAIN equ 1000
IDC_BTN1 equ 1001
IDC_BTN2 equ 1002
IDC_Text equ 1003
.data?
hInstance dd ?
.code
;对话框过程
_ProcDlgMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam
mov eax,uMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDC_BTN1
invoke _incCounter
invoke SetDlgItemInt,hWnd,IDC_Text,eax,FALSE
.elseif ax == IDC_BTN2
invoke _decCounter
invoke SetDlgItemInt,hWnd,IDC_Text,eax,FALSE
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,IDD_MAIN,NULL,addr _ProcDlgMain,NULL
invoke ExitProcess,NULL
end start
资源文件demoDll.rc
#define IDD_MAIN 1000
#define IDC_BTN1 1001
#define IDC_BTN2 1002
#define IDC_Text 1003
#define IDC_STC1 -1
IDD_MAIN DIALOGEX 10,10,150,100
CAPTION "Dll例子"
FONT 8,"MS Sans Serif",0,0,0
STYLE 0x10CF0000
EXSTYLE 0x00000080
BEGIN
CONTROL "增加",IDC_BTN1,"Button",0x50010000,21,45,39,15
CONTROL "减少",IDC_BTN2,"Button",0x50010000,81,45,39,15
CONTROL "0",IDC_Text,"Static",0x50000000,81,24,39,9
CONTROL "Dll内部计数器:",IDC_STC1,"Static",0x50000000,21,24,60,12
END
导出dll所需的说明文件demoDll.def
EXPORTS _incCounter
_decCounter
用于开发编写的include文件demoDll.inc
_incCounter proto
_decCounter proto
编译命令:
ml /c /coff demoDll.asm
link /dll /subsystem:windows /def:demoDll.def demoDll.obj
ml /c /coff useDll1.asm
rc demoDll.rc
link /subsystem:windows useDll1.obj demoDll.res
学习笔记:
例子笔记简单,仅供了解:
在编程的时候我们会用到各种库文件,库中有资源、功能函数等。
在动态链接库出现之前,我们在编译的时候将这些库文件链接到程序中去,
程序运行时这些库的代码随着程序一同装入内存,而windows是多任务的系统,
如果有多个不同的程序使用相同的库,意味着将在内存中装入多份同样的代码,显然浪费内存。
为了解决这个问题,动态链接库诞生了
这种库文件不参与程序的编译过程,它是一种独立的PE文件,事先编译好,独立存在磁盘上,
常见的是dll后缀的文件。在程序运行时,一旦用到dll,会动态加载dll到内存中,通过
windows的内存映射技术,很容易把物理内存中的dll代码映射到不同的进程(程序)中,
完成物理内存到虚拟内存的映射,以供不同的进程使用,这样就解决了静态库的痛点问题。
这种库文件的格式很简单,如上demoDll.asm文件,和一般程序相比,
多了个入口点函数_EntryDll,这个函数的名字随意,但参数的格式是固定的,第一个参数是
dll的句柄,通常可以在Dll初始化的时候获取,第二个参数是宿主进程在调用dll时给出的
调用状态,第三个是保留参数,无用。
可以看到demoDll中除了入口点函数外一共3个函数,_CheckCounter函数是dll内部使用,
其他两个函数用来供其他进程使用,那么问题是如何使用呢?
demoDll.asm源代码编写完成后,还需要写一个格式为.def后缀的文件,用来告诉其他程序,
哪些dll的函数是可用用的,如demoDll.def,这样在加载demoDll.dll到内存的时候def文件
中定义的两个函数就可见了。inc文件是函数声明,useDll.asm简单演示了如何使用dll,
编译命令中包括了如何编译dll文件和exe文件
懒得写了就到这吧,挺简单的仔细看看就会了。