动态库的执行时间
2007-05-02 09:31:55 来源:WEB开发网此文章是针对怜香的系列专题教程"从DOS到Win32"中第8篇文章的后续,读此文之前请先阅读怜香的文章.
当程序中引用了动态库后,WINDOWS是先远行程序呢?还是先加载动态库呢?
为了搞清这个问题,我们将MyDLL.ASM和10.ASM稍作修改如下:
;================MyDLL.ASM================
;例:将EDX:EAX中的值转换成十进制输出形式字符串。
;文件名:MyDll.asm,这是动态链接库的源程序
;编译模式="DLL"
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
OutEdxEax PROTO: DWORD
.DATA
szText0 db "哈哈哈...MyDLL加载",0
szText1 db "MyDLL第一次插入进程的地址空间",0
szText2 db "MyDLL从进程的地址空间卸出",0
szText3 db "同一进程的新线程生成",0
szText4 db "同一进程的线程销毁",0
szText5 db "MyDLL的函数OutEdxEax调用成功",0
.code
;DllEntry是动态链接库的入口,当动态链接库被加载/卸载时,
;或同一进程的线程生成/退出时,都会调用该入口函数
;当然,函数名不一定非是这个,但要和最后的End DllEntry保持一致。
DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD
.if reason==DLL_PROCESS_ATTACH 动态链接库第一次插入进程的地址空间
invoke MessageBox,NULL,addr szText1,addr szText0,MB_OK
mov eax,TRUE
ret
.elseif reason==DLL_PROCESS_DETACH 动态链接库从进程的地址空间卸出
invoke MessageBox,NULL,addr szText2,addr szText0,MB_OK
mov eax,FALSE
ret
.elseif reason==DLL_THREAD_ATTACH ;同一进程的新线程生成
invoke MessageBox,NULL,addr szText3,addr szText0,MB_OK
mov reason,TRUE
ret
.elseif reason==DLL_THREAD_DETACH ;同一进程的线程销毁
invoke MessageBox,NULL,addr szText4,addr szText0,MB_OK
mov eax,FALSE
ret
.endif
DllEntry Endp
;将EDX:EAX中的值转换成十进制输出形式字符串,很熟悉吧,前面的例子中有的!
;比如:EDX=0,EAX=01234567H,则转换后的字符串为:
; -> '19088743',0
OutEdxEax proc uses ebx esi edi,lpString
mov edi,lpString 指向存放结果的地址
mov esi,lpString
mov ecx,10 转换成十进制
.while eax!=0 || edx!=0
push eax
mov eax,edx
xor edx,edx
div ecx
mov ebx,eax
pop eax
div ecx
add dl,'0'
mov [edi],dl 存放结果
inc edi
mov edx,ebx
.endw
mov BYTE ptr [edi],0;字符串以0为结尾
dec edi
.while edi>esi 结果前变后,后变前!
mov al,[esi]
xchg al,[edi]
mov [esi],al
inc esi
dec edi
.endw
invoke MessageBox,NULL,addr szText5,addr szText0,MB_OK
ret
OutEdxEax endp
end DllEntry
;================10.ASM================
;例:文件名:10.asm
;调用MyDll.dll,看能否正常工作
.386
.model flat,stdcall
option casemap:none
include windows.inc
include mydll.inc
include masm32.inc
include user32.inc
include kernel32.inc
includelib mydll.lib
includelib masm32.lib
includelib user32.lib
includelib kernel32.lib
.DATA
szText db "哈哈哈...10.exe运行",0
.data?
CharOut db 100 dup(?)
.code
start:
invoke MessageBox,NULL,addr szText,addr szText,MB_OK
mov edx,12345678h
mov eax,87654321h
invoke OutEdxEax,addr CharOut ;用我们自己的程序转换!
invoke StdOut,addr CharOut
invoke ExitProcess,NULL
end start
好了,将如上修改存盘,编译运行。看到啥啦?似乎也明白了些东东哈!
对啦,我们可以看到:此时WINDOWS先加载动态库,再运行程序。
如果我们把10.ASM再作如下修改,并存盘为10_01.ASM
;================10_01.ASM================
;文件名:10_01.asm
;调用MyDll.dll,看能否正常工作
.386
.model flat,stdcall
option casemap:none
include windows.inc
include masm32.inc
include user32.inc
include kernel32.inc
includelib masm32.lib
includelib user32.lib
includelib kernel32.lib
.DATA
szText db "哈哈哈...10_01.exe运行",0
MyDllFileName db "e:\masm32\xlfancy\mydll.dll",0
CallFuncName db "OutEdxEax",0
.data?
CharOut db 100 dup(?)
MyDLLHandle dd ?
OutEdxEaxAddr dd ?
.code
start:
invoke MessageBox, NULL, addr szText, addr szText, MB_OK
invoke OutEdxEax, addr CharOut ;用我们自己的程序转换!
invoke LoadLibrary, offset MyDllFileName
or eax, eax
jz ExitPro
mov MyDLLHandle, eax
invoke GetProcAddress, eax, offset CallFuncName
or eax, eax
jz FreeLib
mov OutEdxEaxAddr, eax
lea eax, CharOut
push eax
mov edx, 12345678h
mov eax, 87654321h
call OutEdxEaxAddr
invoke StdOut,addr CharOut
FreeLib:
invoke FreeLibrary, MyDLLHandle
ExitPro:
invoke ExitProcess, NULL
end start
编译运行。这时看到啥啦?咦,此时WINDOWS先运行程序,再加载动态库。
以上就是动态库的两种不同的调用方法。经过这两种不同的调用方法,
我们可以粗略地认识和理解WINDOWS加载EXE和DLL的次序和不同。(狗屁!其实我根本就#@$#%#%$%)
以上都在本机编译通过,可就是看不到结果。(折腾了半天,不只所以,JMP...)
不管了,没犯路线错误就行...(马马乎乎,也敢贴出来$%$#%$%%&%&^%,"砰",怎么有砖打到脑袋上?¥#¥%¥%……%)
更多精彩
赞助商链接