下面是一个使用 NASM 编译生成 DLL(动态链接库)的完整实例。我们将创建一个简单的 DLL,其中包含一个导出的函数,然后在 NASM 中编译并使用 link.exe
将其链接成 DLL 文件。
1. 编写汇编代码
创建一个名为 mydll.asm
的文件,并输入以下内容:
global _AddNumbers@8
section .text
; 导出的函数 AddNumbers
; 参数: 两个 32 位整数 (通过堆栈传递)
; 返回值: 两个数的和
_AddNumbers@8:
; 函数序言
push ebp
mov ebp, esp
; 从堆栈中获取参数
mov eax, [ebp + 8] ; 第一个参数
mov ecx, [ebp + 12] ; 第二个参数
; 计算两个数的和
add eax, ecx
; 函数尾声
pop ebp
ret 8 ; 清理堆栈并返回
2. 编译汇编代码
使用 NASM 编译 mydll.asm
,生成一个目标文件(OBJ 文件):
nasm -f win32 mydll.asm -o mydll.obj
3. 链接生成 DLL
使用 link.exe
将生成的 .obj
文件链接成 DLL 文件。你需要指定适当的库文件路径和导出函数。假设你使用的是 Visual Studio 或 Windows SDK,可以使用以下命令:
link.exe /dll /def:mydll.def /out:mydll.dll mydll.obj /libpath:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86" kernel32.lib
其中,mydll.def
文件用于定义导出的函数。创建一个名为 mydll.def
的文件,并输入以下内容:
LIBRARY mydll
EXPORTS
_AddNumbers@8
解释:
-
/dll
:指定生成 DLL 文件。 -
/def:mydll.def
:指定 DEF 文件,用于定义导出的函数。 -
/out:mydll.dll
:指定输出文件名为mydll.dll
。 -
/libpath:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86"
:指定库文件路径(根据你的 Windows SDK 安装路径调整)。 -
kernel32.lib
:链接kernel32.dll
库,这是基本依赖。
4. 验证 DLL
你可以使用 dumpbin
工具查看生成的 DLL 文件中的导出函数,以验证导出是否正确:
dumpbin /exports mydll.dll
你应该会看到类似以下的输出,表明 _AddNumbers@8
函数已经成功导出:
ordinal hint RVA name
1 0 _AddNumbers@8
5. 使用生成的 DLL
现在你可以在其他程序中加载并使用这个 DLL。例如,使用 C 语言编写一个简单的程序来调用这个 DLL 中的 AddNumbers
函数:
#include <windows.h>
#include <stdio.h>
typedef int (*ADD_NUMBERS)(int, int);
int main() {
HINSTANCE hLib = LoadLibrary("mydll.dll");
if (hLib == NULL) {
printf("Failed to load DLL\n");
return 1;
}
ADD_NUMBERS AddNumbers = (ADD_NUMBERS)GetProcAddress(hLib, "_AddNumbers@8");
if (AddNumbers == NULL) {
printf("Failed to get function address\n");
FreeLibrary(hLib);
return 1;
}
int result = AddNumbers(3,