亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? ?

?? 匯編中調用動態鏈接庫的一個例子。
??
字號:
第十七課 動態鏈接庫


--------------------------------------------------------------------------------
本課中,我們將學習DLLs,它們到底是什么和如何創建它們。
  
理論:
如果您編程的時間非常長,就會發現很多的程序之間其實有相當多的重復代碼。每編一個程序就重寫一遍這些代碼既沒必要又浪費時間。在DOS時代,一般的做法是把這些重復的代碼寫成一個個的函數,然后把它們按類別放到不同的庫文件中去。當要使用這些函數時,只要把您的目標文件(.obj)文件和先前存放在庫文件中的函數進行鏈接,鏈接時鏈接器會從庫文件中抽取相關的信息并把它們插入到可執行文件中去。這個過程叫做靜態鏈接。C運行時庫就是一個好例子。這樣的庫的缺點是您在每一個調用庫函數的程序中都必須嵌入同一函數的拷貝,這顯然很浪費磁盤。在DOS時代畢竟每一時刻僅有一個程序在運行,所以浪費的還只是磁盤而已,在多任務的WINDOWS時代就不僅浪費磁盤,還要浪費寶貴的內存了。


在WINDOWS中,由于有多個程序同時運行,如果您的程序非常大的話,那將消耗相當多的內存。WINDOWS的解決辦法是:使用動態鏈接庫。動態鏈接庫從表面上看也是一大堆的通用函數,不過即使有多個程序調用了它,在內存中也僅僅只有動態鏈接庫的唯一一份拷貝。WINDOWS是通過分頁機制來作到這一點的。當然,庫的代碼只有一份,但是每一個應用程序要有自己單獨的數據段,要么就會亂掉。
不象舊時的靜態鏈接庫,它并不會把這些函數的可執行代碼放入到應用程序中去,而是當程序已經在內存中運行時,如果需要調用該函數時才調入內存也即鏈接。這也就是為什么把它叫做“動態”的原因所在。另外您還可以動態地卸載動態鏈接庫,當然要求這時沒有其它的應用程序在使用它,否則就要一直等到最后一個使用它的函數也不再使用該動態鏈接庫時才能去卸載它。
為了正確的調用庫和給庫函數分配內存空間,在編譯和鏈接應用程序時,必須把重定位等一些消息插入到執行代碼中去,以便載入正確的庫,并給庫函數分配正確的地址。
那么這些信息從哪里得到呢?引入庫。引入庫包含足夠的信息,鏈接器從中抽取足夠的信息(注意區別:靜態鏈接庫放入的是可執行代碼)把它們放入到可執行文件中去。當WINDOWS的加載器裝入應用程序查看到有DLL時,它會查找該庫文件,如果沒有查到,就報錯退出,否則就把它映射進進程的地址空間,并修正函數調用語句的地址。 
如果沒有引入庫呢?當然我們也可以調用動態鏈接庫中的任意函數。只不過您必須知道調用的函數是否在庫中而且是否在庫的引出名字表中,另外還需要知道該函數的參數個數和參數的類型。

(譯者加:說到這里,讓我想起了一件很有名的事。<<Undocumented Windows>>一書的作者Angel Schudleman 曾經利用此方法來跟蹤微軟Win3x系統動態鏈接庫中未公開的函數,因為在微軟給程序員提供的系統動態鏈接庫的引入庫中沒有提供這些函數的原型,所以您無法在鏈接時把這些函數的信息鏈接到可執行文件中去,而為了某種目的您又要使用這些函數,您就可以在執行時加載動態鏈接庫并得到這些函數的地址,從而和調用其它的庫函數一樣使用這些未公開的函數。由于這本書的巨大影響,當時許多程序員紛紛在它們的程序中調用未公開函數,甚至在寫商業程序時也這么做。這種走偏峰的做法引起了微軟的反感,后來微軟在它Win3x的改進版中不再把那些未公開函數列入系統動態鏈接庫的引出名字表,這樣也就無法再利用這種方法來調用未公開的函數了。)

當您讓系統的加載器為您加載動態庫時,如果不能找到庫文件,它就會提示一條“A required .DLL file, xxxxx.dll is missing”,這樣您的應用程序就無法運行,即使該庫對您的應用程序來說并不重要。 
如果您選擇在程序運行時自己加載該庫,就沒有這種問題了。 
如果您知道足夠的信息,就可以調用系統未公開的函數。 
如果您調用LoadLibrary函數加載庫,就必須再調用GetProcAddress函數來得到每一個您想調用的函數的地址,GetProcAddress會在動態鏈接庫中查找函數的入口地址。由于多余的步驟,這樣您的程序執行起來會慢一點,但是并不明顯。 
明白了LoadLibrary函數的優缺點,下面我們就來看看如何產生一個動態鏈接庫。下面的代碼是一個動態鏈接庫的框架: 
;-------------------------------------------------------------------------------------- 
;                           DLLSkeleton.asm 
;-------------------------------------------------------------------------------------- 
.386 
.model flat,stdcall 
option casemap:none 
include \masm32\include\windows.inc 
include \masm32\include\user32.inc 
include \masm32\include\kernel32.inc 
includelib \masm32\lib\user32.lib 
includelib \masm32\lib\kernel32.lib 

.data 
.code 
DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD 
        mov  eax,TRUE 
        ret 
DllEntry Endp 
;--------------------------------------------------------------------------------------------------- 
;下面是一個空函數,您可以象下面一樣插入您的函數。 
;---------------------------------------------------------------------------------------------------- 
TestFunction proc 
    ret 
TestFunction endp 

End DllEntry 

;------------------------------------------------------------------------------------- 
;                              DLLSkeleton.def 
;------------------------------------------------------------------------------------- 
LIBRARY   DLLSkeleton 
EXPORTS   TestFunction 
  

上面是一個動態鏈接庫的框架,每一個DLL必須有一個入口點函數,WINDOWS每一次在做下面的動作時會調用該入口點函數: 

當動態鏈接庫被加載時 
當動態鏈接庫卸載時 
同一進程的線程生成時 
同一進程的線程退出時 
DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD 
        mov  eax,TRUE 
        ret 
DllEntry Endp 

入口點函數的名稱無所謂只要您讓語句“END<函數名>”中的函數名和前面的相同就可以了。該函數共有三個參數,只有前面兩個是重要的。
hInstDLL是該動態鏈接庫模塊的句柄。它和進程的實例句柄不一樣。如果您以后要用,可以保存它,因為以后再要獲得它不容易。
根據不同的時機,reason傳入的值可能是下面的四個值中的一個: 

DLL_PROCESS_ATTACH 動態鏈接庫第一次插入進程的地址空間時。當傳入的參數是該值時,您可以做一些初始化的工作。 
DLL_PROCESS_DETACH 動態鏈接庫從進程的地址空間卸出時。您可以在此做一些清理的工作。譬如:釋放內存等。 
DLL_THREAD_ATTACH 新線程生成。 
DLL_THREAD_DETACH 線程銷毀。 
如果想要庫中的代碼繼續執行,返回TRUE,否則返回FALSE,那樣動態鏈接庫就不會加載了。譬如:您想分配一塊內存,如果不成功的話就退出,這時您就可以返回FALSE。那樣動態鏈接庫就不會加載了。
您可以加入的函數,它們的位置并不重要,把它們放在入口點函數的前面或后面都可以。只是如果您想要它們能被其它的程序調用的話,就必須把它們的名字放到模塊定義文件(.def)中去。
動態鏈接庫在它們自己的編譯過程就需要,而不只是提供給其它要引用它的程序參考。他們如下:

LIBRARY   DLLSkeleton 
EXPORTS   TestFunction 

第一行是必須的。LIBRARY 定義了DLL的模塊名稱。它必須和動態鏈接庫的名稱相同。
EXPORTS關鍵字告訴鏈接器該DLL的引出函數,也就是其它程序可以調用的函數。舉個例子:其它的程序想要調用函數TestFunction ,我們就把它放到EXPORTS中。
還有就是,鏈接器的選項中必須放入開關項:/DLL 和/DEF<DLL文件名>,就像下面這樣: 

link /DLL /SUBSYSTEM:WINDOWS /DEF:DLLSkeleton.def /LIBPATH:c:\masm32\lib DLLSkeleton.obj 

編譯器的開關選項是一樣的,即:/c /coff /Cp。在您鏈接好后,鏈接器會生成.lib 和.dll文件。前者是引入庫,當其它的程序要調用您的動態鏈接庫中的函數時就需要該引入庫,以便把必要的信息加入到其可執行文件中去。
接下來我們來看看如何使用LoadLibrary函數來加載一個DLL。 

;--------------------------------------------------------------------------------------------- 
;                                      UseDLL.asm 
;---------------------------------------------------------------------------------------------- 
.386 
.model flat,stdcall 
option casemap:none 
include \masm32\include\windows.inc 
include \masm32\include\user32.inc 
include \masm32\include\kernel32.inc 
includelib \masm32\lib\kernel32.lib 
includelib \masm32\lib\user32.lib 

.data 
LibName db "DLLSkeleton.dll",0 
FunctionName db "TestHello",0 
DllNotFound db "Cannot load library",0 
AppName db "Load Library",0 
FunctionNotFound db "TestHello function not found",0 

.data? 
hLib dd ?                                         ; 動態鏈接庫的句柄 (DLL) 
TestHelloAddr dd ?                        ; TestHello 函數的地址 

.code 
start: 
        invoke LoadLibrary,addr LibName 
;--------------------------------------------------------------------------------------------------------- 
; 調用LoadLibrary,其參數是欲加載的動態鏈接庫的名稱。如果調用成功,將返回該DLL的句柄。 否則返回NULL。該句柄可以傳給 :library函數和其它需要動態鏈接庫句柄的函數。 
;----------------------------------------------------------------------------------------------------------- 
        .if eax==NULL 
                invoke MessageBox,NULL,addr DllNotFound,addr AppName,MB_OK 
        .else 
                mov hLib,eax 
                invoke GetProcAddress,hLib,addr FunctionName 
;----------------------------------------------------------------------------------------------------------- 
; 當您得到了動態鏈接庫的句柄后,把它傳給GetProcAddress函數,再把您要調用的函數的名稱 也傳給該函數。如果成功的話,它:會返回想要的函數的地址,失敗的話返回NULL。除非卸載該 動態鏈接庫否則函數的地址是不會改變的,所以您可以把它保存到一個:全局變量中以備后用。 
;----------------------------------------------------------------------------------------------------------- 
                .if eax==NULL 
                        invoke MessageBox,NULL,addr FunctionNotFound,addr AppName,MB_OK 
                .else 
                        mov TestHelloAddr,eax 
                        call [TestHelloAddr] 
;----------------------------------------------------------------------------------------------------------- 
; 以后您就可以和調用其它函數一樣調用該函數了。其中要把包含函數地址信息的變量用方括號括起來。
;----------------------------------------------------------------------------------------------------------- 
                .endif 
                invoke FreeLibrary,hLib 
;----------------------------------------------------------------------------------------------------------- 
;調用FreeLibrary卸載動態鏈接庫。
;----------------------------------------------------------------------------------------------------------- 
        .endif 
        invoke ExitProcess,NULL 
end start 

使用LoadLibrary函數加載動態鏈接庫,可能要自己多做一些工作,但是這種方法確實是提供了許多的靈活性。 

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲欧美日韩国产手机在线| 亚洲精品乱码久久久久久| 91在线精品秘密一区二区| 无码av免费一区二区三区试看| 欧美精品一区二区三区一线天视频 | 视频一区在线视频| 国产清纯白嫩初高生在线观看91| 欧美中文字幕久久| 波多野结衣一区二区三区| 免费观看一级特黄欧美大片| 亚洲私人黄色宅男| 久久久久久久精| 51精品久久久久久久蜜臀| 91黄色免费观看| 成人精品免费网站| 国内精品国产成人| 男女性色大片免费观看一区二区| 亚洲精选视频在线| 亚洲国产精品高清| 久久综合色之久久综合| 欧美日韩一级二级三级| 色综合天天综合网国产成人综合天| 国精产品一区一区三区mba视频| 亚洲福利一区二区| 亚洲激情中文1区| 国产精品女人毛片| 国产欧美日韩精品a在线观看| 日韩三级电影网址| 欧美一区二区三区视频在线观看| 欧美性生活大片视频| 色综合天天综合网国产成人综合天| 高清不卡一二三区| 国产电影精品久久禁18| 精品一区中文字幕| 久88久久88久久久| 久久精品国产99久久6| 免费欧美高清视频| 免费在线一区观看| 免费不卡在线视频| 蜜桃一区二区三区在线| 日韩高清在线一区| 免费xxxx性欧美18vr| 捆绑变态av一区二区三区| 另类小说色综合网站| 免费观看成人av| 老司机免费视频一区二区三区| 美女尤物国产一区| 国内精品在线播放| 国产成人精品免费网站| 成熟亚洲日本毛茸茸凸凹| 国产不卡在线播放| 97精品久久久久中文字幕| 91小视频在线免费看| 色婷婷香蕉在线一区二区| 日本韩国精品一区二区在线观看| 在线观看网站黄不卡| 欧美日韩国产综合一区二区| 91精品一区二区三区在线观看| 欧美一区二区三区的| 亚洲精品在线网站| 国产精品私人自拍| 亚洲一区二区影院| 日本欧美韩国一区三区| 久久99精品国产麻豆不卡| 国产成人在线视频网站| 99久久婷婷国产综合精品| 色88888久久久久久影院按摩| 欧美色精品在线视频| 91精品国产综合久久国产大片| 精品日韩一区二区三区| 中文字幕不卡的av| 亚洲国产中文字幕在线视频综合 | 久久丝袜美腿综合| 国产精品嫩草99a| 亚洲成a人片在线不卡一二三区| 另类人妖一区二区av| 成人免费毛片嘿嘿连载视频| 色哟哟一区二区三区| 精品国产一区久久| 亚洲色图视频网站| 久久99精品久久久久久久久久久久 | 色哟哟亚洲精品| 日韩午夜小视频| 国产精品人妖ts系列视频| 一区二区成人在线视频| 久久av资源站| 色视频成人在线观看免| 日韩欧美黄色影院| 亚洲精品视频在线| 激情久久久久久久久久久久久久久久| gogogo免费视频观看亚洲一| 69久久99精品久久久久婷婷| 亚洲国产精品二十页| 午夜影视日本亚洲欧洲精品| 国产成人精品www牛牛影视| 欧美色综合天天久久综合精品| 精品国产百合女同互慰| 亚洲一区二区综合| 国产成人在线观看免费网站| 欧美片在线播放| 国产精品你懂的在线欣赏| 久久国产福利国产秒拍| 欧美性高清videossexo| 欧美极品少妇xxxxⅹ高跟鞋| 蜜桃传媒麻豆第一区在线观看| 91丨porny丨在线| 久久精品视频网| 日韩国产欧美一区二区三区| 91丨porny丨国产入口| 久久蜜臀中文字幕| 麻豆一区二区在线| 欧美日韩dvd在线观看| 亚洲天堂av一区| 国产福利91精品一区二区三区| 日韩视频国产视频| 亚洲成a人v欧美综合天堂下载| 99视频在线观看一区三区| 久久综合精品国产一区二区三区 | 亚洲国产精品综合小说图片区| 国产精品1区2区3区在线观看| 在线播放/欧美激情| 一区二区三区 在线观看视频| 99精品久久久久久| 国产欧美一区二区三区沐欲 | 色国产精品一区在线观看| 中文无字幕一区二区三区| 韩国女主播一区二区三区| 91精品国产品国语在线不卡| 亚洲成年人影院| 欧美日本在线一区| 亚洲第一激情av| 欧美午夜一区二区三区| 亚洲美女免费视频| 不卡视频一二三四| 国产精品免费av| 成人激情午夜影院| 一区在线观看视频| 97精品久久久午夜一区二区三区 | 亚洲v中文字幕| 欧美偷拍一区二区| 亚洲h动漫在线| 欧美日本乱大交xxxxx| 婷婷夜色潮精品综合在线| 欧美日韩国产a| 美女高潮久久久| 日韩午夜激情电影| 九九热在线视频观看这里只有精品| 欧美一级欧美三级在线观看| 欧美aaa在线| 久久精品人人做人人综合| 成人综合日日夜夜| 综合网在线视频| 欧美无砖砖区免费| 麻豆91在线观看| 久久婷婷国产综合精品青草| 成人激情小说网站| 一区二区三区成人| 日韩欧美在线1卡| 国产一区二区精品久久| 中文字幕第一区二区| 日本久久一区二区| 日韩一区精品视频| 精品国产伦理网| 国产91在线|亚洲| 1000精品久久久久久久久| 欧美综合一区二区| 久色婷婷小香蕉久久| 国产精品私人影院| 欧美日韩精品高清| 黑人巨大精品欧美一区| 国产精品久久久久一区| 91极品视觉盛宴| 久久精品国产亚洲a| 亚洲国产精品国自产拍av| 欧美午夜寂寞影院| 精品伊人久久久久7777人| 1024成人网| 日韩欧美一级在线播放| 成人激情黄色小说| 亚洲大片在线观看| 久久精品亚洲一区二区三区浴池| 91老司机福利 在线| 老司机午夜精品99久久| 亚洲人成网站精品片在线观看| 在线综合+亚洲+欧美中文字幕| 国产成人av电影在线观看| 亚洲va欧美va人人爽午夜| 久久精品人人做人人爽97| 欧美日本一区二区| www.激情成人| 久久精品国产精品亚洲红杏| 亚洲人成7777| 亚洲精品一区二区精华| 欧美日韩一级片网站| 成人丝袜18视频在线观看| 天堂av在线一区| 亚洲婷婷综合久久一本伊一区| 欧美精品一区二区三| 欧美日韩免费高清一区色橹橹| 国产99久久久久久免费看农村|