动态库的执行时间

此文章是针对怜香的系列专题教程"从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...)
不管了,没犯路线错误就行...(马马乎乎,也敢贴出来$%$#%$%%&%&^%,"砰",怎么有砖打到脑袋上?¥#¥%¥%……%)

时间: 2025-01-01 17:16:57

动态库的执行时间的相关文章

Linux下如何用GCC编译动态库

  本文主要解决以下几个问题 1 为什么要使用库? 2 库的分类 3 创建自己的库 或许大家对自己初学 Linux时的情形仍记忆尤新吧.如果没有一个能较好的解决依赖关系的包管理器,在Linux下安装软件将是一件及其痛苦的工作.你装a包时,可能会提示你要先装b包,当你费尽心力找到b包时,可能又会提示你要先安装c包.我就曾被这样的事搞的焦头烂额,至今一提起rpm仍心有余悸,头皮发麻.说是一朝被蛇咬,十年怕井绳怕也不为过. Linux下之所以有这许多的依赖关系,其中一个开发原则真是功不可没.这个原则就

关于Linux静态库和动态库的分析

原文:http://linux.chinaunix.net/techdoc/net/2009/02/04/1060670.shtml 1.什么是库 在windows平台和linux平台下都大量存在着库.本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的本质不同,因此二者库的二进制是不兼容的. 本文仅限于介绍linux下的库.2.库的种类linux下的库有两种:静态库和共享库(动态库). 二者的不同点在于代码被载入的时刻不同.静态库的代码在编译

GNU/Linux中动态库的搜索路径的指定方法汇总

动态链接时.执行时搜索路径顺序: 1.编译目标代码时使用-L指定的动态库搜索路径: 2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径: 3.配置文件/etc/ld.so.conf中指定的动态库搜索路径: 4.默认的动态库搜索路径/lib: 5.默认的动态库搜索路径/usr/lib. 以上的3-5步中,不再需要手动地指定动态库搜索路径了, 有一个可以进行配置更新默认的搜索路径的命令: ldconfig ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及

C++Builder中动态库的链接问题

动态库链接到应用程序中主要有两种方式:隐式链接和显式链接.隐式链接是常用方式. 如果应用程序和动态库是分别在不同开发平台上编制的,动态库的导入库(lib文件)可能会与应用程序的开发平台所要求的导入库格式不相容,从而在应用程序与动态库隐式链接时,出现程序链接错误:contains invalid OMF record.例如在C++Builder开发平台上链接Visual C++制作的动态库时,就会出现上述的错误.解决这一问题,可以采用两种方法:显式连接法和使用C++Builder中提供的导入库生成

C#调用非托管动态库中的函数

C#如何调用一个非托管动态库中的函数呢,比如用VC6写的动态库,总之C#调用动态库的过程是比Java调用DLL动态库方便快捷多了,下面举例说明这个过程. 1.创建一个非托管动态库 代码如下: //这一句是声明动态库输出一个可供外不调用的函数原型. extern "C" __declspec(dllexport) int add( int , int ); int add( int a, int b) { //实现这个函数returna+b; } 注意上面代码,一定要加上 extern&

Linux下生成使用动态库和静态库

Linux中有两类函数库,动态库和静态库 静态库: 这类库一般都是以.a为后缀名的文件,利用静态库函数编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中. 编译后的执行程序就不需要外部的函数库支持,但也有其缺点,就是一旦静态函数库改变了,那么程序就必须重新编译. 动态库: 这类库的一般都是以.so为后缀名的,相对于静态库函数库来说,动态函数库在编译的时候并没有被编译进目标代码中.当程序执行到相关函数时才调用该函数库里的相应函数,因此动态库函数库所产生的可执行文件比较小,由于函数库

异常-C#调用动态库,无法加载 DLL"xx.dll": 找不到指定的模块。

问题描述 C#调用动态库,无法加载 DLL"xx.dll": 找不到指定的模块. 报错内容:System.DllNotFoundException: 无法加载 DLL"XX.dll": 找不到指定的模块. (异常来自 HRESULT:0x8007007E). 网上的各种方法我都试过了,都是这样 我把目标平台改成x64,报错就变成:System.BadImageFormatException: 试图加载格式不正确的程序. (异常来自 HRESULT:0x8007000

【C/C++学院】0801-重定向以及文件扫描/二进制加密解密/简单加密/按照密码加密/动态库与静态库

重定向以及文件扫描 #define _CRT_SECURE_NO_WARNINGS//关闭安全检查 #include<stdio.h> #include<stdlib.h> void main1() { char str[100] = { 0 }; scanf("%s", str); printf("str=%s\n", str); system(str); } void main2() { char str[100] = { 0 }; fs

C#调用c++的动态库dll演示例程

1.首先编写c++动态库 extern "C" __declspec(dllexport) int __stdcall add(int x, int y) { return x + y; } extern "C" __declspec(dllexport) extern "C"使得在C++中使用C编译方式成为可能.在"C++"下定义"C"函数,需要加extern "C"关键词.用exte