输入函数的高效和低效调用

源码

//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++的虚函数表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值