2.2.位与位或位异或在操作寄存器时的特殊作用

来源:互联网 发布:淘宝网天天特价女装 编辑:程序博客网 时间:2024/05/02 01:02

2.2.位与位或位异或在操作寄存器时的特殊作用

1.寄存器操作的要求(特定位改变而不影响其他位)
(1)arm是统一编址的,arm中有很多内部外设,soc通过向这些内部外设的寄存器写入一些特定的值来完成操作。这个内部外设进而操控硬件,所以说读写寄存器就是在操控硬件。
(2)在设定特定位时不改变其他位,而且寄存器的特点就是按位进行规划和使用。
(3)而修改寄存器中的特定值的一般步骤是,读-改-写。读取一次寄存器的值时32位的(一个int),而要想修改其中的一位必须全部读出32位的内容。修改完以后再统一写入寄存器中。

2.特定位清零用&
(1)回顾:二进制位和1位与无变化,与0位与变成0。
(2)若要把其中特定位改成0,其他位不变,可以使用位与1的方法。
(3)举例:把0xaaaaaaaa的第八位到第十五为清零,
分析:
第一步:要把0xaaaaaaaa这个十六进制数的第8到15位清零,就得让8-15位和0位与,而其他位不能发生变化。
第二步:要得到一个十六进制数,让该数的8-15位是0,其他位是1,先写出这样的二进制数的0-31位是:1111 1111 1111 1111 0000 0000 1111 1111
第三步:把这个二进制数转换为十六进制数得到0xffff00ff
第四步:让之前寄存器中的数(0xaaaaaaaa)和我们现在得到的数(0xffff00ff)进行位与,即可完成8-15位清零。

a = 0xaaaaaaaa //1010 1010 1010 1010 '1010 1010' 1010 1010b = 0xffff00ff //1111 1111 1111 1111 '0000 0000' 1111 1111c = a & b c == 0xaaaaaa00aa //1010 1010 1010 1010 '0000 0000' 1010 1010                     //这样8-15位就被清零了。结果为0xaaaa00aa                     //十六进制一位等于二进制四位

3.特定位置1用|
(1)回顾:位或:(二进制数)与1位或变成1,与0位或无变化。
(2)特定位置1,其他位不变采用位或。
(3)举例:把0xaaaaaaa0八位二进制数的0-3位置1,其他位不变。
分析:
第一步:要把0xaaaaaaa0这个十六进制数的第0到3位清零,就得让0-3位和1位或,而其他位不能发生变化。
第二步:要得到一个十六进制数,让该数的0-3位是1,其他位是0,先写出这样的二进制数的0-31位是:0000 0000 0000 0000 0000 0000 0000 1111
第三步:把这个二进制数转换为十六进制数得到0xf
第四步:让之前寄存器中的数(0xaaaaaaa0)和我们现在得到的数(0xf)进行位或,即可完成0-3位置一。

a = 0xaaaaaaa0;//1010 1010 1010 1010 1010 1010 1010 '0000'b = 0xf //0000 0000 0000 0000 0000 0000 0000 '1111'c = a | b;     c = 0xaaaaaaaf  //1010 1010 1010 1010 1010 1010 1010 '1111'                //这样0-3位就被置一了。结果为0xaaaaaaaf

4.取反~
(1)把一个数按照二进制位进行取反
(2)举例:把0xf0取反
分析:
第一步:要给一个数取反首先要得到这个数的二进制。0xf0的二进制数是:1111 0000
第二步:按照每一位进行取反,0变1,1变0。
第三步:取反后得到0000 1111,把之转换成十六进制是:0xf

a = 0xf0;// 1111 0000c = ~b;  c == 0xf;//0000 1111          //注意:这里的变量都占32位,这里省略了8-31位,用不到的位,编译器自动补0。

5.特定位取反用^
(1)回顾:位异或,(二进制位)与1位或会取反,与0异或无变化。
(2)位异或真值表:
  00111
  11100
  ^(位异或)
  —————-
  11011
(3)举例:把0xa的0-1位取反,其他位不改变
分析:
第一步:把要被取反的数转换为二进制数:0xa–>1010
第二步:构建一个数让他的特定位为1,这个特定位是指上面的要被取反的数的要被取反的位。比如我要向上面的数的0-1位取反,我构建的数的0-1位就为1,其他位为0,所以我构建的数位 :0011
第三步:把我构建的二进制数转换成十六进制的,0011–>0x

  a = 0xa//10'10'  b = 0x3    //00'11'  c = a^b;  c == 0xb;  //10'11'          //这样0xa的0-1位就取反了,而其他位没有发生变化

总结:
(1)十六进制一位等于二进制四位,32位平台下int数据类型占32位,寄存器也是32位的,分配的变量占32位,我们用不到的位,编译器自动补0。
(2)注意~和^的区别。前者是给所有位取反的。后者可以完成给特定位取反。
(3)在单片机或者嵌入式中,位运算符号是很常用的,尤其是在Linux内核中。

0 0