为Cortex-M0优化C或汇编代码的大小

时间:2015-01-10 12:51:58

标签: c optimization cortex-m

我需要减少Cortex-M0微处理器的代码膨胀。

启动时,必须将ROM数据复制到RAM数据一次。因此我有这段代码:

void __startup( void ){
  extern unsigned int __data_init_start;
  extern unsigned int __data_start;
  extern unsigned int __data_end;

  // copy .data section from flash to ram
  s = & __data_init_start;
  d = & __data_start;
  e = & __data_end;
  while( d != e ){ 
    *d++ = *s++;
  }
}

编译器生成的汇编代码如下所示:

  ldr   r1, .L10+8
  ldr   r2, .L10+12
  sub   r0, r1, r2
  lsr   r3, r0, #2
  add   r3, r3, #1
  lsl   r1, r3, #2
  mov   r3, #0
.L4:
  add   r3, r3, #4
  cmp   r3, r1
  beq   .L9
.L5:
  ldr   r4, .L10+16
  add   r0, r2, r3
  add   r4, r3, r4
  sub   r4, r4, #4
  ldr   r4, [r4]
  sub   r0, r0, #4
  str   r4, [r0]
  b .L4

如何优化此代码以使代码大小最小?

2 个答案:

答案 0 :(得分:1)

编译器(或您!)没有意识到要复制的范围是end - start。似乎有一些不必要的数据正在进行 - 循环中的2 addsub。此外,在我看来,编译器确保要制作的副本数是4的倍数。然后,显而易见的优化是以确保它是提前的!下面我假设它是(如果没有,bne将会失败,并愉快地继续复制和践踏你的记忆。)

使用我十年前的ARM汇编程序knowlegde(是的,这是一个主要的免责声明),以及后递增,我认为以下简短的代码段是它可以被浓缩的内容。从18指令下降到8,还不错。如果有效。

  ldr   r1, __data_init_start
  ldr   r2, __data_start
  ldr   r3, __data_end
  sub   r4, r3, r2
.L1:
  ldr   r3, [r1], #4  ; safe to re-use r3 here
  str   r3, [r2], #4
  subs  r4, r4, #4
  bne   L1

答案 1 :(得分:1)

可能该平台保证写入unsigned int *您可以更改unsigned int *值(即它不会利用类型不匹配别名规则)。

然后代码效率低下,因为e是一个全局变量,生成的代码逻辑必须考虑到写入*d可能会改变e的值。

至少使e本地化可以解决这个问题(大多数编译器都知道,从C的角度来看,从不使用其地址的本地别名是不可能的。)