動態連結庫(DLL)是 Windows 模組化程式設計的基石,允許多程式共享同一程式碼拷貝於記憶體中,節省資源並利於維護。本文涵蓋 DLL 架構原理、匯入庫機制、LoadLibrary/GetProcAddress 動態載入技術,並提供 MASM 建立 DLL 與呼叫 DLL 的完整範例框架。
LoadLibrary + GetProcAddress 手動載入並取得函式位址(執行期連結)。匯入庫僅含符號與重定位資訊,不含實際程式碼;靜態庫則含完整機器碼。
; 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
link /DLL /SUBSYSTEM:WINDOWS /DEF:DLLSkeleton.def /LIBPATH:c:\masm32\lib DLLSkeleton.obj
產出 DLLSkeleton.dll 與 DLLSkeleton.lib(匯入庫)。
DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD
hInstDLL:DLL 模組控制碼(非進程實例控制碼),難以事後取得,建議自行保存。reason 四種值:
DLL_PROCESS_ATTACH:首次載入,執行初始化DLL_PROCESS_DETACH:卸載,釋放資源DLL_THREAD_ATTACH:新執行緒建立DLL_THREAD_DETACH:執行緒結束TRUE 允許載入繼續,FALSE 導致載入失敗。適用於無匯入庫、需條件載入、或呼叫未文件化函式的情境。
; UseDLL.asm
invoke LoadLibrary, addr LibName ; LibName = "DLLSkeleton.dll"
.if eax==NULL
; 載入失敗處理
.else
mov hLib, eax
invoke GetProcAddress, hLib, addr FunctionName ; FunctionName = "TestHello"
.if eax==NULL
; 函式不存在
.else
mov TestHelloAddr, eax
call [TestHelloAddr] ; 間接呼叫
.endif
invoke FreeLibrary, hLib ; 釋放 DLL
.endif
LoadLibrary:成功返回模組控制碼,失敗 NULL。系統維護參考計數,重複載入同一 DLL 僅增加計數。GetProcAddress:在 DLL 匯出表查找函式名稱,返回入口位址。位址在 DLL 未卸載前固定,可緩存。FreeLibrary:遞減參考計數,歸零時真正卸載。extern "C" 避免修飾;MASM PROC 預設不修飾。DLL 是 Windows 程式設計的核心重用機制。掌握匯入庫靜態連結與 LoadLibrary 動態載入兩種模式,理解 DllEntry 生命週期通知、匯出表定義、連結器選項,即可靈活構建模組化應用系統。