您的位置:首页 > 编程语言

函数指针使用与直接函数调用对程序代码大小的影响

2010-03-12 16:35 525 查看
/**************************************************************

*File

Name:

size_test.c

*Description:

*

测试使用函数指针间接调用函数,以及直接

*

调用函数对程序代码大小的影响。

*Author

:

Chryice

*Date

:

2010-2-26

*Modify List:

***************************************************************/

#include <stdio.h>

int max(int v1, int v2);

void test_entry1(void);

void test_entry2(void);

typedef int (*fun_ptr)(int, int);

fun_ptr gFunPtr = NULL;

int main(int argc ,char** argv)

{

gFunPtr = max;

test_entry1();

test_entry2();

return 0;

}

int max(int v1, int v2)

{

return ((v1 > v2) ? v1 : v2);

}

void test_entry1(void)

{

int v1 = 23, v2 = 30, m;

m = max(v1, v2);

printf("Max value: %d/n", m);

}

void test_entry2(void)

{

int v1 = 56, v2 = 21, m;

m = gFunPtr(v1, v2);

printf("Max Value: %d/n", m);

}

//对应汇编代码如下

/*

从左至右分为三列,分别为:

程序在RAM
中的内存地址

机器代码

汇编代码

因为ARM
体系结构采用的是精简指令系统,每条指令代码固定为
4
字节,即
32bits.

*/

test_entry2(000080db)

[0xb580] push {r7,r14}

000080de

[0x2038] mov r0,#0x38

;参数传递设置

000080e0

[0x2115] mov r1,#0x15

000080e2

[0x4a10] ldr r2,0x00008124 ; = #0x00009ff4;把全局函数指针变量
gFunPtr
的存储地址放到
r2
寄存器中

000080e4

[0x6812] ldr r2,[r2,#0]

;获取
gFunPtr
中保存的数据,也即把
gFunPtr
所指向函数的内存地址保存到寄存器
r2
中。

000080e6

[0xf8f9f000] bl __call_via_r2

;通过
r2
寄存器,进行函数调用。

000080ea

[0x1c01] mov r1,r0

000080ec

[0xa00e] adr r0,0x8128

000080ee

[0xf8d7f000] bl _printf

000080f2

[0xbd80] pop {r7,pc}

;pc也即
r14
寄存器,
pop pc
能实现函数调用的返回

max

[0x4288] cmp r0,r1

000080f6

[0xdc00] bgt 0x80fa ; (max + 0x6)

000080f8

[0x1c08] mov r0,r1

000080fa

[0x4770] bx r14

test_entry1

[0xb580] push {r7,r14}

000080fe

[0x2017] mov r0,#0x17

00008100

[0x211e] mov r1,#0x1e

00008102

[0xfff7f7ff] bl max

00008106

[0x1c01] mov r1,r0

00008108

[0xa00b] adr r0,0x8138

0000810a

[0xf8c9f000] bl _printf

0000810e

[0xbd80] pop {r7,pc}

main

[0xb580] * push {r7,r14}

00008112

[0x480d] ldr r0,0x00008148 ; = #0x000080f5

;???按道理应该是
0x000080f4
,也即函数
max
的内存地址
???

00008114

[0x4903] ldr r1,0x00008124 ; = #0x00009ff4

00008116

[0x6008] str r0,[r1,#0]

00008118

[0xfff0f7ff] bl test_entry1

0000811c

[0xffdef7ff] bl test_entry2

00008120

[0x2000] mov r0,#0

00008122

[0xbd80] pop {r7,pc}

//全局数据
:
从全局数据可以看出,对于传递给
printf
函数的格式化字符串,对于每个调用都保存了一份,所以,如果格式化字符串相同的话,最好

//提取出来保存到一个全局常量变量中。这样就可以减少重复,节省空间。

00008124

[0x00009ff4] dcd 0x00009ff4 ....

00008128

[0x2078614d] dcd 0x2078614d Max

0000812c

[0x756c6156] dcd 0x756c6156 Valu

00008130

[0x25203a65] dcd 0x25203a65 e: %

00008134

[0x00000a64] dcd 0x00000a64 d...

00008138

[0x2078614d] dcd 0x2078614d Max

0000813c

[0x756c6176] dcd 0x756c6176 valu

00008140

[0x25203a65] dcd 0x25203a65 e: %

00008144

[0x00000a64] dcd 0x00000a64 d...

00008148

[0x000080f5] dcd 0x000080f5 ....

/*_testentry1和
test_entry2
比较
,
使用函数指针进行函数调用的情况多了两行指令:

000080e2

[0x4a10] ldr r2,0x00008124 ; = #0x00009ff4;把全局函数指针变量
gFunPtr
的存储地址放到
r2
寄存器中

000080e4

[0x6812] ldr r2,[r2,#0]

;获取
gFunPtr
中保存的数据,也即把
gFunPtr
所指向函数的内存地址保存到寄存器
r2
中。

使用函数指针进行函数间接调用一次,代码大小(仅考虑函数调用的代码片段)多了0x000080e6 - 0x000080e2 = 4
个字节
;

使用函数指针的好处就是动态解析,诸如C++
里面的虚函数表来实现多态。

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐