共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电子工程师创研计划】技术变现通道已开启~ | |
发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
【EEPW在线】E起听工程师的声音! | |
“我踩过的那些坑”主题活动——第001期 | |
高校联络员开始招募啦!有惊喜!! | |
【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
送您一块开发板,2025年“我要开发板活动”又开始了! | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
电流检测模块MAX4080S被打赏10分 | |
【我踩过的那些坑】calloc和malloc错误使用导致跑飞问题排查被打赏50分 | |
多组DCTODC电源方案被打赏50分 | |
【我踩过的那些坑】STM32cubeMX软件的使用过程中的“坑”被打赏50分 | |
新手必看!C语言精华知识:表驱动法被打赏50分 | |
【我踩过的那些坑】杜绑线问题被打赏50分 | |
【我踩过的那些坑】STM32的硬件通讯调试过程的“坑”被打赏50分 | |
【我踩过的那些坑】晶振使用的问题被打赏100分 | |
【我踩过的那些坑】电感选型错误导致的处理器连接不上被打赏50分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏10分 |