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

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

*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++ 里面的虚函数表来实现多态。

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值