首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

把局部变量从char或者short类型转换成int类型

把局部变量从char或者short类型转换成int类型

把局部变量从char或者short类型转换成int类型,可以改善性能并减小代码尺寸,其实,这种转换函数类型参数也有同样的效果,看下面的例子,将2个16位的值相加,其他第2个数先减半,然后返回一个16位的和:

Short add-v1(short a,short b)

{

   Return a +(b>>1);

}

虽然这个函数只是一个简单的算术运算,但是对于观察编译器碰到的问题是一个很好的例子,输入值a,b和返回值都存放在32位的ARM寄存器中,编译器是否应该考虑这些32位数值在short类型的范围之间呢?或者编译器是否应该通过对低16位数据进行符号位扩展,充填32位寄存器,强制把数值限制在上述范围之间呢?编译器必须把调用者和被调用者作出一致的决策,不是调用者,就是被调用者,必须把数据转换为short类型。

如果参数可以不缩小到定义的数据类型范围,那么称这种函数参数传递是宽的,反之,则称为窄的。观察add-v1的汇编输出结果,就可以知道编译器所来用的是那种形式,如果编译器传递参数是宽的。那么被调用者就必须把参数缩小到正确的用的是哪种形式。如果编译器传递参数是窄的。那么调用者必须缩小参数范围。如果编译器返回值是窄的。那么被调用者就必须在返回前缩小回值的范围。

对于ADS的armcc来说,函数参数传递和返回值都是窄的。换句话说,调用者要处理调用参数,而被调用者要处理返回值,编译器采用函数的ANSI原型来决定函数参数的数据类型。

函数add-v1在armcc下的输出结果显示,编译器把返回值的类型转换为short类型的范围之内,这就说明参数传递和返回值都是窄的。

Add-v1

  Add  r0,r0,r1,ASR #1   ;r0=(int)a+((int) b>>1)

  MOV  r0,r0,LSL #16     

  MOV  r0,r0,ASR #16      ;r0=(short) r0

  MOV  pc,r14              ;return r0

Gcc编译器更为谨慎,对参数值的范围不作任何假设,这个版本的编译器,在调用者和被调用者中将输入参数缩小到short类型的数据范围,同时也都将返回值转换为short类型,下面是add-v1由gcc编译后的代码:

  Add-v1-gcc

  MOV r0,r0,LSL #16

MOV r1,r1,LSL #16

MOV r1,r1,LSL #17               ;r1=(int)b>>1

ADD r1,r1,r0,ASR #16            ;r1+=(int)a

MOV r1,r1,LSL #16

MOV r0,r1,ASR #16               ;r0(short)r1

MOV pc,1r                        ;return r0

尽管宽和窄的函数调用规则各有其优点,但是char或者short类型的函数参数和返回值都会产生额外的开销,导致性能的下降,并增加了代码尺寸。所以,即使是传输一个8位的数据,函数参数和返回值使用int类型也会更有效。

继承事业,薪火相传
返回列表