出处:
http://www.stmfans.com/bbs/viewt ... a=page%3D1#pid14725IAR 中的位操作,在有些情况下,有点出人意料。
比如,我想清除某个变量的某一位,
例:
_DEVICE_RCC.CR &= ~(BIT(
1)); // 清除CR的第(1+1)位,相当於 _DEVICE_RCC.CR &= 0xFFFF FFFD
(以下内容的编译为IAR5.20)
\ 00000000 0748 LDR.N R0,??main_0 ;; 0x40021000
\ 00000002 0168 LDR R1,[R0, #+0]
\ 00000004 0222
MOVS R2,#+2 ;//主要是这一条和下一条语句, MOV(S),赋值 \ 00000006 9143
BICS R1,R1,R2 ;//BIC(S),位清除 \ 00000008 0160 STR R1,[R0, #+0]
上面中间两条的汇编的意思很明显,让 R2 = 2 , 再清除 R1 的第2位.
但如果,把原程序稍改一下,
_DEVICE_RCC.CR &= ~(BIT(
8)); // 清除CR的第(8+1)位,
(以下内容的编译为IAR5.20)
\ 00000000 0748 LDR.N R0,??main_0 ;; 0x40021000
\ 00000002 0168 LDR R1,[R0, #+0]
\ 00000004 6FF48072
MVN R2,#+256 ;/
/主要是这一条和下一条语句, MVN 取补码 \ 00000008 1140
ANDS R1,R2,R1 ;
//AND(S) 位“与” \ 0000000A 0160 STR R1,[R0, #+0]
它就变成了上面的形式了。
上面中间两条的汇编的意思是:
R2= 0x00000100 (256) ,再 R2 = ~R2 = FFFFFEFF,然后再与R1相与 R1 = R1 & R2
虽然,最终的结果是一样的,目的也是一样的,但不同的位置,IAR却做出了不同的汇编语句,怪不?
小结:第1~8位 ( BIT(0) ~ BIT(7) ) , IAR 使用第一种的方式,也就是
位清除的方式。
第9~32位 ( BIT(8) ~ BIT(31), IAR 使用的是第二种的方式,也就是
取反,再与。
==================================================================
以上的
IAR 5.20的编译环境下的汇编,但在
IAR5.30,则变了。
15 _DEVICE_RCC.CR &= ~BIT(1);
\ 00000008 0168 LDR R1,[R0, #+0]
\ 0000000A 21F00201
BIC R1,R1,#0x2 \ 0000000E 0160 STR R1,[R0, #+0]
19 _DEVICE_RCC.CR &= ~BIT(8);
\ 00000014 0168 LDR R1,[R0, #+0]
\ 00000016 21F48071
BIC R1,R1,#0x100 \ 0000001A 0160 STR R1,[R0, #+0]
20
21 _DEVICE_RCC.CR &= ~BIT(18);
\ 0000001C 0168 LDR R1,[R0, #+0]
\ 0000001E 21F48021
BIC R1,R1,#0x40000 \ 00000022 0160 STR R1,[R0, #+0]
不管是哪个位,都是使用
位清除的指令,比以前的优化了很多。