- 源码
- OD调试
- func1
- func2
- 原理
//dll.h #pragma once void func1(); __declspec(dllimport) void func2();
#include "dll.h"
#pragma comment(lib,"../Debug/Dll.lib")
int main()
{
func1(); //输出"func1"
func2(); //输出"func2"
return 0;
}
OD调试
func1
011F16AE E8 CEFAFFFF call 011F1181 011F16B3 8BF4 mov esi, esp 011F16B5 FF15 00901F01 call dword ptr [<&Dll.#2>] ; Dll.func2 011F1181 /E9 58050000 jmp func1 ; jmp 到 offset Dll.func1 011F1186 |E9 59050000 jmp func2 ; jmp 到 offset Dll.func2
offset Dll.func1:
011F16DE >- FF25 04901F01 jmp dword ptr [<&Dll.func1>] ; Dll.func1 011F16E4 >- FF25 00901F01 jmp dword ptr [<&Dll.#2>] ; Dll.func2
dll.func1:
0FE41140 > /E9 1B0A0000 jmp func1 0FE41145 > |E9 66120000 jmp func2
func1:
0FE41B60 > 55 push ebp 0FE41B61 8BEC mov ebp, esp ...func2
011F16AE E8 CEFAFFFF call 011F1181 011F16B3 8BF4 mov esi, esp 011F16B5 FF15 00901F01 call dword ptr [<&Dll.#2>] ; Dll.func2 0FE41140 > /E9 1B0A0000 jmp func1 0FE41145 > |E9 66120000 jmp func2
func2没有跳转到offset Dll.func1,而是直接跳转到dll.func2。
原理输入函数有高效和低效两种调用情况。
默认对输入api使用低效形式。
解释:编译器无法区分输入函数调用和普通函数调用,对每个函数调用,编译器使用call指令。call后的地址由链接器填充,不是函数指针,而是代码中jmp指令的实际地址。
由于使用了额外的jmp,所以执行时间长一些。
要想优化,可以在声明处加上__declspec(dllimport),告诉编译器这个函数来自dll。所以主函数的func2是这样的:
011F16B5 FF15 00901F01 call dword ptr [<&Dll.#2>] ; Dll.func2
这种jmp有点像c++的虚函数表。



