匠人的百宝箱 https://passport2.21ic.com/?24110 [收藏] [复制] [RSS]

日志

IAR中的位操作之一:位清除(转贴)

已有 1410 次阅读2010-3-17 05:40 |个人分类:编程技巧|系统分类:单片机| IAR, 位操作

出处:http://www.stmfans.com/bbs/viewt ... a=page%3D1#pid14725

IAR 中的位操作,在有些情况下,有点出人意料。
比如,我想清除某个变量的某一位,
例:
  _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]

不管是哪个位,都是使用位清除的指令,比以前的优化了很多。

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)