0

编译此代码时

void FastRead()
{
    register uint32_t cnt = 1000, sample;
    register uint8_t *dst = data;
    asm volatile(
    "loop1:"
        "ldr     %[sample], [%[src]]\n\t"
        "strb    %[sample], [%[dst], #1]!\n\t"
        "subs    %[cnt],1 \n\t"                
        "bne     loop1\n\t"
        : [cnt] "+r" (cnt), [dst] "+r" (dst), [sample] "=r" (sample)
        : [src] "r" (&CORE_PIN16_PINREG)
    );
}

在“编译”之后,寄存器分配产生这个代码

000004dc <_Z8FastReadv>:
     4dc:   f44f 737a   mov.w   r3, #1000   ; 0x3e8
     4e0:   4a03        ldr r2, [pc, #12]   ; (4f0 <loop1+0xc>)
     4e2:   4904        ldr r1, [pc, #16]   ; (4f4 <loop1+0x10>)

000004e4 <loop1>:
     4e4:   6809        ldr r1, [r1, #0]  ;         <--  ?!?!?!?!?!?
     4e6:   f802 1f01   strb.w  r1, [r2, #1]!
     4ea:   3b01        subs    r3, #1
     4ec:   d1fa        bne.n   4e4 <loop1>
     4ee:   4770        bx  lr
     4f0:   1fff8820    .word   0x1fff8820
     4f4:   400ff050    .word   0x400ff050

我将 src 指定为只读寄存器,但不应意味着允许“编译器”覆盖它,是吗?快速的解决方法是让每个变量都可以读/写(+r)。

但是是什么原因造成的,这是一个错误,或者任何人都可以解释我为什么会发生这种情况?

编辑:抱歉忘了提,这是我们在 linux 上使用 gcc 编译器(arm-none-eabi-g++ 版本 4.7.2 和 4.8.4)

4

1 回答 1

1

这不是编译器中的错误。asm 操作的输入/输出的编译器模型是这样执行的:

  1. 读取输入
  2. 做手术
  3. 写输出

因此,允许编译器将任何输出值分配给与输入值相同的寄存器。

当您在 asm 语句中有一系列指令时,例如在您的示例中,一些输出是在读取一些输入之前写入的。答案可在https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm的内联 asm 约束文档中找到。

您需要解决此问题的部分是:

使用“&” 对不得与输入重叠的所有输出操作数的约束修饰符(请参阅修饰符)。否则,GCC 可以将输出操作数与不相关的输入操作数分配在同一个寄存器中,假设汇编代码在产生输出之前消耗其输入。如果汇编代码实际上包含多条指令,则此假设可能是错误的。

如果您将输出约束更改为:

: [cnt] "+&r" (cnt), [dst] "+&r" (dst), [sample] "=&r" (sample)

然后你会解决这个问题。

于 2015-03-25T01:38:00.837 回答