32位汇编:实验12动态链接库

创建动态链接库(Sample.dll)

步骤1:创建导出定义文件 Sample.def

在实验目录下新建文本文件:

EXPORTS _Mod

步骤2:创建DLL源代码 Sample.asm

同一目录下创建Sample.asm

.386 .model flat, stdcall option casemap :none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 文件定义(根据实际路径修改) ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include D:\\BYQ\\masm32v11r\\masm32\\include\\windows.inc ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .data? dwCounter dd ? ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .code ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; dll 的入口函数 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DllEntry proc _hInstance,_dwReason,_dwReserved mov eax,TRUE ret DllEntry Endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; dll 的导出函数 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _Mod proc uses ecx edx _dwNumber1,_dwNumber2 xor edx,edx mov eax,_dwNumber1 mov ecx,_dwNumber2 .if ecx div ecx mov eax,edx .endif ret _Mod endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> End DllEntry

步骤3:创建头文件 Sample.inc

创建Sample.inc供调用方使用:

`;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Version 1.0 ; Date: 2004.05.01 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Sample.dll 导出函数: ; ;invoke _Mod,dwNumber1,dwNumber2 ; 输入:dwNumber1 和 dwNumber2 为两个整数 ; 输出:两数的模 dwNumber1 % dwNumber2 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_Mod proto dwNumber1:dword,dwNumber2:dword`

步骤4:编译和链接DLL

打开命令提示符,执行:

; 汇编生成目标文件 ml /c /coff Sample.asm

发现环境变量忘记添加了

这里因为个人环境原因我们设置临时环境变量

再次进行汇编

汇编成功 ; 链接生成DLL Link /subsystem:windows /Dll /Def:Sample.def Sample.obj

目录下生成 Sample.dll, Sample.lib, Sample.exp


创建调用程序(UseDll.exe)

步骤5:创建资源文件 UserDll.rc

准备图标文件Main.ico

创建UserDll.rc

#include <resource.h> //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #define ICO_MAIN 1000 #define DLG_MAIN 1000 #define IDC_NUM1 1004 #define IDC_NUM2 1005 #define IDC_MOD 1006 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ICO_MAIN ICON "Main.ico" //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DLG_MAIN DIALOG 186, 132, 173, 79 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "DLL例子" FONT 9, "宋体" { GROUPBOX "取模函数测试", -1, 4, 37, 164, 32, BS_GROUPBOX EDITTEXT IDC_NUM1, 11, 50, 43, 12, ES_NUMBER LTEXT "%", -1, 57, 52, 5, 8 EDITTEXT IDC_NUM2, 64, 50, 43, 12, ES_NUMBER LTEXT "=", -1, 110, 52, 5, 8 EDITTEXT IDC_MOD, 117, 50, 43, 12, ES_READONLY }

步骤6:创建调用程序源码 UserDll.asm

创建UserDll.asm

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .386 .model flat, stdcall option casemap :none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 文件定义(根据实际路径修改) ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include D:\\BYQ\\masm32v11r\\masm32\\include\\windows.inc include D:\\BYQ\\masm32v11r\\masm32\\include\\user32.inc includelib D:\\BYQ\\masm32v11r\\masm32\\lib\\user32.lib include D:\\BYQ\\masm32v11r\\masm32\\include\\kernel32.inc includelib D:\\BYQ\\masm32v11r\\masm32\\lib\\kernel32.lib include Sample.inc includelib Sample.lib ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Equ 等值定义 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ICO_MAIN equ 1000 DLG_MAIN equ 1000 IDC_NUM1 equ 1004 IDC_NUM2 equ 1005 IDC_MOD equ 1006 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .code ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam mov eax,wMsg .if eax == WM_CLOSE invoke EndDialog,hWnd,NULL .elseif eax == WM_COMMAND mov eax,wParam .if ax == IDC_NUM1 || ax == IDC_NUM2 invoke GetDlgItemInt,hWnd,IDC_NUM1,NULL,FALSE push eax invoke GetDlgItemInt,hWnd,IDC_NUM2,NULL,FALSE pop ecx invoke _Mod,ecx,eax invoke SetDlgItemInt,hWnd,IDC_MOD,eax,FALSE .endif .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> start: invoke GetModuleHandle,NULL invoke DialogBoxParam,eax,DLG_MAIN,NULL,offset _ProcDlgMain,NULL invoke ExitProcess,NULL ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end start


编译和运行调用程序

编译资源、汇编、链接

在工作目录下依次执行:

`; 编译资源 rc UserDll.rc

; 汇编 ml /c /coff UserDll.asm

; 链接 Link /subsystem:windows UserDll.obj UserDll.res`

成功生成exe文件

步骤10:运行程序

UserDll.exe


知识梳理

一、Windows DLL 的基本概念与生命周期

  • 什么是 DLL(动态链接库):运行时由操作系统装载的可执行模块(PE 格式)。它把函数/资源打包供其它程序(或其它 DLL)在运行时调用。好处:代码复用、节省内存、可替换升级。

  • 加载时机

    • 显式加载:LoadLibrary / FreeLibrary

    • 隐式加载:程序在链接时引用了 DLL(通过 .lib),进程启动时由 loader 自动加载

  • 生命周期回调 :系统在装载/卸载或线程创建/退出时会调用 DLL 主入口 DllMain(也叫 DllEntry)。

    • DllMain(hinst, DLL_PROCESS_ATTACH, NULL):进程装载

    • DLL_PROCESS_DETACH:进程卸载

    • DLL_THREAD_ATTACH / DLL_THREAD_DETACH:线程事件(注意:不一定会收到线程事件)

  • DLL 必须返回 TRUE 才能被成功载入 (实验中 mov eax, TRUE 即返回 TRUE)。


二、PE/链接器相关(.def、.lib、.exp、导出表)

  • .def(Module-Definition)文件

    指定导出的符号(函数名/序号)。示例:EXPORTS _Mod。它告诉 linker 将 _Mod 写入导出表(Export Table)。

  • 导出方式

    • 使用 .def(显式列出)

    • 使用编译器关键字 __declspec(dllexport)(C/C++)

  • 生成的文件

    • .dll:运行时要的库

    • .lib(import library):链接时使用(目标程序用它生成对 DLL 的引用),并非静态库

    • .exp:导出信息(中间文件)

  • Export Table / IAT

    • Export Table:DLL 中记录可被外部调用的函数(名字/序号/地址)

    • Import Address Table (IAT):可执行文件或另一个 DLL 的表,运行时被 loader 修补为指向目标 DLL 的实际函数地址(thunk)


三、Calling Convention(调用约定)

实验用的是 stdcall (MASM option casemap:none + invoke 默认用 stdcall)------必须理解:

  • stdcall 特点

    • 参数由右向左压栈(最后一个参数先压)

    • 调用方调用 CALL,被调用方(callee)负责清理栈(ret N

    • 返回值放在 EAX(32-bit 整数),但某些操作(如 div)余数放 EDX

  • cdecl(对比)

    • 同样右向左压栈,但调用者清理栈 ,用于可变参数函数(printf
  • fastcall 等 :部分参数传寄存器(MSVC 有 __fastcall,有平台差异)

  • 在汇编层面要留意 uses 子句_Mod proc uses ecx edx _dwNumber1,_dwNumber2 表示该过程会改写 ecx/edx,MASM 会自动保存/恢复这些寄存器给调用者(自动 push/pop),以防破坏调用者期望的寄存器值(callee-saved vs caller-saved 概念)。

相关推荐
资料,小偿9 小时前
4.101基于8086国旗图案proteus8.9,8086彩灯图案流水灯图案,国期图案仿真,四个开关四种模式。近期本人原创
汇编·proteus
资料,小偿3 天前
4.29.3五种波形发生器8086波形发生器,锯齿波脉冲波正弦波三角波直流信号含调试视频➕18页5000字原创报告软件流程图proteus8.9近期原创的,
汇编·proteus
T.Ree.3 天前
汇编_读写内存
开发语言·汇编·c#
量子炒饭大师4 天前
【一天一个计算机知识】—— 【编程百度】翻译环境与运行环境
c语言·汇编·c++·gitee·机器翻译
资料,小偿5 天前
4.98基于8086倒车测距8086测距ACD0809proteus8.9仿真,汇编语言源程序
汇编·proteus
万象.6 天前
GNU汇编语法和Cortex-A7常用汇编指令
服务器·汇编·gnu
资料,小偿6 天前
4.95基于8086流水灯霓虹彩灯控制器,8086彩灯控制器proteus8.9仿真文件+源码功能四个开关对应四种模式。
汇编·proteus
YeGop7 天前
51单片机定时器函数分享(8051汇编)
汇编·嵌入式硬件·51单片机
YeGop8 天前
51单片机汇编实现DHT11读取温湿度
汇编·嵌入式硬件·51单片机