编译此代码时
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指定为只读寄存器,但不应该代表编译器&#39;被允许覆盖它,是吗?快速解决方法是使每个变量都可读/写(+ r)。
但是导致这种情况的原因是,这是一个错误,还是有人可以解释为什么会发生这种情况?
编辑:抱歉忘了提一下,这个我们在Linux上使用gcc编译器(arm-none-eabi-g ++版本4.7.2和4.8.4)
答案 0 :(得分:1)
这不是编译器中的错误。用于asm操作的输入/输出的编译器模型是它们的执行方式如下:
因此,允许编译器将任何输出值分配给与输入值相同的寄存器。
如果在asm语句中有一系列指令,例如在您的示例中,则在读取某些输入之前会写入一些输出。答案可在https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm的内联asm约束文档中找到。
解决此问题所需的部分是:
对所有不能与输入重叠的输出操作数使用'&amp;'约束修饰符(请参阅修饰符)。否则,GCC可以将输出操作数分配到同一寄存器中作为无关输入操作数,前提是汇编代码在产生输出之前消耗其输入。如果汇编程序代码实际上包含多个指令,则此假设可能为false。
如果您将输出约束更改为:
: [cnt] "+&r" (cnt), [dst] "+&r" (dst), [sample] "=&r" (sample)
然后你将解决问题。