共3条
1/1 1 跳转至页
问
两条功能基本一样的语句为什么编译后的结果会不同?
前边的一条编译后是一条位测试指令,
而后一条编译后是一条IO输入指令,
不知为何,郁闷。
下面的那条指令让我找了两天原因了,
可是找不到原因,请高手指点。
128:atmega16.c **** if(bit_is_set(ADCSRA,ADSC))
477 .LM68:
478 017c 3699 sbic 38-0x20,6
129:atmega16.c ****
130:atmega16.c ****
131:atmega16.c ****
132:atmega16.c **** if(bit_is_set(UCSRA,UDRE))
480 .LM69:
481 017e 8BB1 in r24,43-0x20 答 1: 测试过了,没有任何问题。不过当你的if后没有任何语句时,就是一个in指令。否则就是sbic指令。
if(bit_is_set(ADCSRA,ADSC)) aa = 7;
178: 36 9b sbis 0x06, 6 ; 6
17a: 02 c0 rjmp .+4 ; 0x180
17c: 87 e0 ldi r24, 0x07 ; 7
17e: 01 c0 rjmp .+2 ; 0x182
else aa=8;
180: 88 e0 ldi r24, 0x08 ; 8
182: 80 93 78 00 sts 0x0078, r24
if(bit_is_set(UCSRA,UDRE)) aa = 12;
186: 5d 9b sbis 0x0b, 5 ; 11
188: 02 c0 rjmp .+4 ; 0x18e
18a: 8c e0 ldi r24, 0x0C ; 12
18c: 01 c0 rjmp .+2 ; 0x190
else aa=13;
18e: 8d e0 ldi r24, 0x0D ; 13
…………………………
if(bit_is_set(ADCSRA,ADSC)) aa = 7;
178: 36 9b sbis 0x06, 6 ; 6
17a: 02 c0 rjmp .+4 ; 0x180
17c: 87 e0 ldi r24, 0x07 ; 7
17e: 01 c0 rjmp .+2 ; 0x182
else aa=8;
180: 88 e0 ldi r24, 0x08 ; 8
182: 80 93 78 00 sts 0x0078, r24
if(bit_is_set(UCSRA,UDRE));
186: 8b b1 in r24, 0x0b ; 11
………………
190: 80 93 78 00 sts 0x0078, r24 答 2: 这是为什么?我刚才按照楼上仁兄所说,试了一下,的确是这样。
我的前一个IF后面是有语句的,而后一个IF的后面是一个空语句。
所以有上面的结果,这是为什么呢? 答 3: 当然有道理了。如果有if指令那么sbic是对了。否则用一个in指令好。因为一个in指令为一个指令周期,而sbic如果跳转则就是两个指令周期了。可见gcc是多么的聪明! 答 4: 要理解定义#define bit_is_set(sfr, bit) (sfr & _BV(bit))
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + 0x20)
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
如果if表达式后有语句,根据C语法定义,必然会生成跳转指令。
但如果if表达式后是空语句,按C语法来说这条if表达式是没有任何意义的,除非 (1) if表达式中含有赋值语句;(2) 表达式中有对volatile变量访问的语句。
而在楼主和版主发现的问题,正是上面所说的第(2)种情况,在这种情况下,编译器必须生成对UCSRA的访问指令,但又无法生成跳转指令(也确实不需要跳转),所以只有生成in指令而不能用sbic,sbis了。 答 5: 谢谢楼上各位老兄指点,在此表示感谢其实我感觉GCC还是挺好用的,生成的代码很简练
前边的一条编译后是一条位测试指令,
而后一条编译后是一条IO输入指令,
不知为何,郁闷。
下面的那条指令让我找了两天原因了,
可是找不到原因,请高手指点。
128:atmega16.c **** if(bit_is_set(ADCSRA,ADSC))
477 .LM68:
478 017c 3699 sbic 38-0x20,6
129:atmega16.c ****
130:atmega16.c ****
131:atmega16.c ****
132:atmega16.c **** if(bit_is_set(UCSRA,UDRE))
480 .LM69:
481 017e 8BB1 in r24,43-0x20 答 1: 测试过了,没有任何问题。不过当你的if后没有任何语句时,就是一个in指令。否则就是sbic指令。
if(bit_is_set(ADCSRA,ADSC)) aa = 7;
178: 36 9b sbis 0x06, 6 ; 6
17a: 02 c0 rjmp .+4 ; 0x180
17c: 87 e0 ldi r24, 0x07 ; 7
17e: 01 c0 rjmp .+2 ; 0x182
else aa=8;
180: 88 e0 ldi r24, 0x08 ; 8
182: 80 93 78 00 sts 0x0078, r24
if(bit_is_set(UCSRA,UDRE)) aa = 12;
186: 5d 9b sbis 0x0b, 5 ; 11
188: 02 c0 rjmp .+4 ; 0x18e
18a: 8c e0 ldi r24, 0x0C ; 12
18c: 01 c0 rjmp .+2 ; 0x190
else aa=13;
18e: 8d e0 ldi r24, 0x0D ; 13
…………………………
if(bit_is_set(ADCSRA,ADSC)) aa = 7;
178: 36 9b sbis 0x06, 6 ; 6
17a: 02 c0 rjmp .+4 ; 0x180
17c: 87 e0 ldi r24, 0x07 ; 7
17e: 01 c0 rjmp .+2 ; 0x182
else aa=8;
180: 88 e0 ldi r24, 0x08 ; 8
182: 80 93 78 00 sts 0x0078, r24
if(bit_is_set(UCSRA,UDRE));
186: 8b b1 in r24, 0x0b ; 11
………………
190: 80 93 78 00 sts 0x0078, r24 答 2: 这是为什么?我刚才按照楼上仁兄所说,试了一下,的确是这样。
我的前一个IF后面是有语句的,而后一个IF的后面是一个空语句。
所以有上面的结果,这是为什么呢? 答 3: 当然有道理了。如果有if指令那么sbic是对了。否则用一个in指令好。因为一个in指令为一个指令周期,而sbic如果跳转则就是两个指令周期了。可见gcc是多么的聪明! 答 4: 要理解定义#define bit_is_set(sfr, bit) (sfr & _BV(bit))
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + 0x20)
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
如果if表达式后有语句,根据C语法定义,必然会生成跳转指令。
但如果if表达式后是空语句,按C语法来说这条if表达式是没有任何意义的,除非 (1) if表达式中含有赋值语句;(2) 表达式中有对volatile变量访问的语句。
而在楼主和版主发现的问题,正是上面所说的第(2)种情况,在这种情况下,编译器必须生成对UCSRA的访问指令,但又无法生成跳转指令(也确实不需要跳转),所以只有生成in指令而不能用sbic,sbis了。 答 5: 谢谢楼上各位老兄指点,在此表示感谢其实我感觉GCC还是挺好用的,生成的代码很简练
共3条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 | |
【FRDM-MCXN947评测】核间通信MUTEX被打赏50分 |