为什么int是MSP430-GCC中的小整数的优先级而不是(无符号)char

时间:2013-11-25 15:33:21

标签: c assembly microcontroller msp430 mspgcc

在msgpcc(GSP for MSP430微控制器)manual作者写道:

  

如果要在函数中使用小整数,请使用int而不是char或unsigned char。生成的代码将更有效,并且在大多数情况下,存储实际上不会被浪费。

为什么int效率更高?

UPD。为什么mspgcc中的(u)int_fast8_t定义为(unsigned) char,而不是(unsigned) int。据我了解,(u)int_fast*_t应该被定义为具有足够大小的最有效类型。

4 个答案:

答案 0 :(得分:5)

一般的经验法则是 CPU在使用原始字大小的整数上运行速度最快。

这当然完全取决于架构,请参阅this similar question的答案,以获得有关该点的更多说明。

答案 1 :(得分:5)

TI已针对其Tiva-C(正式Stellaris)MCU发布了有关该主题的应用笔记。

在“简介”部分中,表格提供了影响性能和大小的因素列表。 因素标签可变大小表明使用小于最佳值的变量可能意味着需要额外的指示来签名或取消签名扩展...

此外,在“变量大小”一节中,它指出:

“当局部变量小于寄存器大小时,通常需要额外的代码。在Stellaris部分,这意味着大小为byte和halfword(分别为char和short int)的局部变量需要额外的代码。从8位或16位微控制器移植可能已将本地转换为较小的大小(以避免太大的问题),这意味着此类代码将运行得更慢并占用更多的代码空间。“

请参阅:http://www.ti.com/lit/an/spma014/spma014.pdf

以下内容由编译器处理,但仍与手头的问题有关:

MSP430是一款16位微处理器。 char只有8位,需要打包以确保所有单词都对齐。例如,3个字符在内存中无法正确对齐。相反,使用16位的整数并始终对齐。

当您使用16的倍数(例如16和32)的变量大小时,您还可以更有效地利用内存。你最终不会用填充来对齐内存。

答案 2 :(得分:4)

通常,不一定特定于此处理器,它与符号扩展和屏蔽有关,需要额外的指令才能忠实地实现C源代码。 16或32或64位处理器中带符号的8位值可能涉及签名扩展的附加指令。 32位处理器上的8位加法可能涉及到0xFF等的额外指令

你应该做一些简单的实验,需要几次迭代,但我很快就找到了显示出差异的东西。

unsigned int fun ( unsigned int a, unsigned int b )
{
    return(a+b)<<3;
}

unsigned char bfun ( unsigned char a, unsigned char b )
{
    return(a+b)<<3;
}


 int sfun (  int a,  int b )
{
    return(a+b)<<3;
}

 char sbfun (  char a,  char b )
{
    return(a+b)<<3;
}

产生

00000000 <fun>:
   0:   0f 5e           add r14,    r15 
   2:   0f 5f           rla r15     
   4:   0f 5f           rla r15     
   6:   0f 5f           rla r15     
   8:   30 41           ret         

0000000a <bfun>:
   a:   4f 5e           add.b   r14,    r15 
   c:   4f 5f           rla.b   r15     
   e:   4f 5f           rla.b   r15     
  10:   4f 5f           rla.b   r15     
  12:   30 41           ret         

00000014 <sfun>:
  14:   0f 5e           add r14,    r15 
  16:   0f 5f           rla r15     
  18:   0f 5f           rla r15     
  1a:   0f 5f           rla r15     
  1c:   30 41           ret         

0000001e <sbfun>:
  1e:   8f 11           sxt r15     
  20:   8e 11           sxt r14     
  22:   0f 5e           add r14,    r15 
  24:   0f 5f           rla r15     
  26:   0f 5f           rla r15     
  28:   0f 5f           rla r15     
  2a:   4f 4f           mov.b   r15,    r15 
  2c:   30 41           ret         

msp430具有指令的字和字节版本,因此当使用小于寄存器大小的变量时,简单的加法或减法不必进行剪切或符号扩展。作为一个程序员,我们可能知道我们只会给sbfun提供一些非常小的数字,但是编译器没有并且必须忠实地实现我们编写的代码,在sfun和sbfun之间生成更多代码。使用不同的编译器和处理器进行这些实验并不难看到这一点,唯一的技巧是创建处理器没有简单指令要解决的代码。

另一个例子

unsigned int fun ( unsigned int a, unsigned int b )
{
    return(a+b)>>1;
}

unsigned char bfun ( unsigned char a, unsigned char b )
{
    return(a+b)>>1;
}

产生

00000000 <fun>:
   0:   0f 5e           add r14,    r15 
   2:   12 c3           clrc            
   4:   0f 10           rrc r15     
   6:   30 41           ret         

00000008 <bfun>:
   8:   4f 4f           mov.b   r15,    r15 
   a:   4e 4e           mov.b   r14,    r14 
   c:   0f 5e           add r14,    r15 
   e:   0f 11           rra r15     
  10:   4f 4f           mov.b   r15,    r15 
  12:   30 41           ret         

答案 3 :(得分:1)

int匹配有问题的处理器的本机大小(16位),因此当您要求存储到unsigned char变量时,编译器可能必须发出额外的代码以确保值介于0到255之间。