zoukankan      html  css  js  c++  java
  • 寄存器读写为什么需要用位操作符

    寄存器读写为什么需要用位操作符

    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 1010
    b = 0xffff00ff //1111 1111 1111 1111 '0000 0000' 1111 1111
    c = 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 0000
    c = ~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内核中。

  • 相关阅读:
    SpringMVC-注解式控制器详解-SpringMVC强大的数据绑定(1)
    SpringMVC-注解式控制器详解-SpringMVC强大的数据绑定
    关于BI商业智能的“8大问”|一文读懂大数据BI
    关于BI商业智能的“8大问”|一文读懂大数据BI
    符号表
    高性能MYSQL读书笔记1
    perl 打包成PAR包 类似JAR包
    perl 包函数变动 需要重新打包
    第一章 数据引用与匿名存储
    换部门与看录像——北漂18年(90)
  • 原文地址:https://www.cnblogs.com/1024E/p/13209640.html
Copyright © 2011-2022 走看看