c - AVR GCC (ATTiny1614) 上的内联汇编优化问题
问题描述
我正在尝试为 ATtiny1614 开发延迟功能(使用 AtmelStudio 7) 有一个现有的平台 _delay_us() 可以做类似的事情,但这与能够调整自己的代码一样是一种学习体验。
为了解决延迟问题以及最小且一致的延迟时间,我决定进行内联汇编。
我做了以下:(片段)
__attribute__((__always_inline__)) static inline void delay_loops(volatile uint32_t numLoops) {
asm volatile(
"loop_1%=: \n\t"
" subi %A[numLoops], 1 \n\t"
" sbci %B[numLoops], 0 \n\t"
" sbci %C[numLoops], 0 \n\t"
" sbci %D[numLoops], 0 \n\t"
" brcc loop_1%= \n\t"
:
:[numLoops] "d" (numLoops)
// d=select upper register (r16-31) only
);
}
int main(void)
{
...
delay_loops(10);
delay_loops(12);
...
}
到目前为止,一切都很好。一切都按预期工作,并生成以下代码:
3ec: 8a e0 ldi r24, 0x0A ; 10
3ee: 90 e0 ldi r25, 0x00 ; 0
3f0: a0 e0 ldi r26, 0x00 ; 0
3f2: b0 e0 ldi r27, 0x00 ; 0
000003f4 <loop_1333>:
3f4: 81 50 subi r24, 0x01 ; 1
3f6: 90 40 sbci r25, 0x00 ; 0
3f8: a0 40 sbci r26, 0x00 ; 0
3fa: b0 40 sbci r27, 0x00 ; 0
3fc: d8 f7 brcc .-10 ; 0x3f4 <loop_1333>
3fe: 8c e0 ldi r24, 0x0C ; 12
400: 90 e0 ldi r25, 0x00 ; 0
402: a0 e0 ldi r26, 0x00 ; 0
404: b0 e0 ldi r27, 0x00 ; 0
00000406 <loop_1341>:
406: 81 50 subi r24, 0x01 ; 1
408: 90 40 sbci r25, 0x00 ; 0
40a: a0 40 sbci r26, 0x00 ; 0
40c: b0 40 sbci r27, 0x00 ; 0
40e: d8 f7 brcc .-10 ; 0x406 <loop_1341>
寄存器预加载给定的循环值,然后迭代该循环数。
但是,如果我将主代码更改为
int main(void)
{
...
delay_loops(12); // changed 10->12
delay_loops(12);
...
}
然后第二次延迟变得似乎无穷无尽(或者至少超出了我的逻辑分析器的范围)。
编译后的程序集显示以下内容:
3ec: 8c e0 ldi r24, 0x0C ; 12
3ee: 90 e0 ldi r25, 0x00 ; 0
3f0: a0 e0 ldi r26, 0x00 ; 0
3f2: b0 e0 ldi r27, 0x00 ; 0
000003f4 <loop_1332>:
3f4: 81 50 subi r24, 0x01 ; 1
3f6: 90 40 sbci r25, 0x00 ; 0
3f8: a0 40 sbci r26, 0x00 ; 0
3fa: b0 40 sbci r27, 0x00 ; 0
3fc: d8 f7 brcc .-10 ; 0x3f4 <loop_1332>
000003fe <loop_1339>:
3fe: 81 50 subi r24, 0x01 ; 1
400: 90 40 sbci r25, 0x00 ; 0
402: a0 40 sbci r26, 0x00 ; 0
404: b0 40 sbci r27, 0x00 ; 0
406: d8 f7 brcc .-10 ; 0x3fe <loop_1339>
输入值 (12) 的初始化不是在 delay_loops() 的第二次“调用”时完成的。程序集只是使用它仍然具有的(更改的)寄存器值继续第二个循环。我只能假设编译器不知道我更改了 r24..27 并假设它们仍然正确初始化为 12,从而优化了正确的初始化。
如何强制正确初始化?
谢谢
解决方案
内联汇编程序手册解释了如果您有一个操作数用于输入和输出,您需要做什么。
按照他们的示例,我认为您应该尝试用以下内容替换以冒号开头的两行:
:[numLoops] "=d" (numLoops)
:"0" (numLoops)
推荐阅读
- kdb - KDB/Q:如何组合多列中的值并对值进行排序?
- python - 使用 %s 格式的记录器消息中的 Python 格式编号?
- javascript - 如何让时钟停止
- django - Django view not executing
- javascript - React 发送 cookie 到 Nodejs
- php - 为什么包含 DDL 语句的事务会抛出异常?
- python - 在一列值中转换一列列表
- css - 如何将图像文本 div 与 flexbox 对齐?
- php - 使用 php mysql 显示从下拉列表中选择值的数据,无需页面刷新或按钮单击
- c - 显示输出问题...(创建节点)