比如,我想清除某个变量的某一位,
例:
_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]
不管是哪个位,都是使用位清除的指令,比以前的优化了很多。