admin管理员组

文章数量:1355559

I have a bit of C code for an ARM Cortex-M0 chip, for which I was investigating the disassembly:

int func2(unsigned a) {
  int h[a];
  for (unsigned i = 0; i < a; i++) {
    h[i] = 0;
  }

  int ch;
  do {
    ch = serial_getc();
    add_position(h, ch);
  } while (ch != '\r');

  return h[0];
}

To my surprise, I found that that the disassembly did the following:

000000ea <func2>:
  ea:   b5b0        push    {r4, r5, r7, lr}
  ec:   af00        add r7, sp, #0
  ee:   0083        lsls    r3, r0, #2
  f0:   3307        adds    r3, #7
  f2:   08db        lsrs    r3, r3, #3
  f4:   00db        lsls    r3, r3, #3
  f6:   466a        mov r2, sp
  f8:   1ad3        subs    r3, r2, r3
  fa:   469d        mov sp, r3

So r3 gets the offset calculated for the new sp to allocate the additional memory on the stack, but it's the three lines starting at f0 that puzzle me. If I understand correctly it's basically doing a "multiply by 4 and round up to a multiple of 8" operation, i.e.:

r0 = 0    => r3 = 0
r0 = 1    => r3 = 8
r0 = 2    => r3 = 8
r0 = 3    => r3 = 16
r0 = 4    => r3 = 16
r0 = 5    => r3 = 24
...

Why is the compiler choosing to do this? The code would be simpler if it just allocated the requested amount.

The code was compiled using:

arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -O -g -Wall -ffreestanding  -c test.c -o test.o

It seems that this is enforced by the calling convention, and on exception entry [1]. However, this documentation only specifies this for ARMv7, whereas the Cortex M0 is ARMv6. In this [2] discussion, it is implied that not much can go wrong if the convention is not followed in a Cortex M0.

So, this leads to the question: What can go wrong in a Cortex M0 if the double-word alignment is not satisfied in assembly code mixed with C code?

The Cortex M0 user guide discusses that the alignment is restored to what it was before the exception. So there is no need to maintain an aligned stack pointer, in case an exception happens.

The Cortex M0 also doesn't have an LDRD instruction, which may require alignment to operate correctly.

[1] [2]

本文标签: assemblyWhy does the compiler allocate too much memoryStack Overflow