本节书摘来自异步社区《嵌入式Linux与物联网软件开发——C语言内核深度解析》一书中的第2章,第2.4节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.4 位运算构建特定二进制数

由前面可知,对寄存器特定位进行置1、清零或者取反,关键点在于要事先构建一个特别的数,这个数和原来的值进行位与、位或、位异或操作,即可达到我们对寄存器操作的要求。

自己去算这个数,显然既费时又费脑,虽然依托工具也可以算出来,但缺点就是不直观。如0X0003803A这个数谁能一下报出转换为二进制后为多少?太难了。既然如此,我们完全可以使用位运算(位与、位或、取反等等)快速地构建我们需要的操作数。

2.4.1 使用移位获取特定位为1的二进制数

最简单的就是用移位来获取一个特定位为1的二进制数。如我们需要一个bit3~bit7为1(隐含意思就是其他位全部为0)的二进制数。

我们可以用计算器或者直接用脑子去想。

这个数便是0b11111000 = 0xf8,而这个数并不容易一下就能想出来。

我们来利用二进制构造。

分析bit3~bit7为1,则该数是由5(7-3+1)个二进制的1构成的,只不过是从bit3开始连续排布的,所以我们就想构造一个从bit0开始连续排布的5个二进制1,左移3位即可实现。而这个数很容易就可以想出来,它就是0x1f,现在对这个数左移3位(0x1f << 3 )是不是就实现了呢。

也许,这个对比还不是很明显,我们再来看一个例子:获取bit3~bit7为1,同时bit23~bit25为1,其余位为0的数。

这个时候你用脑子去想是不是开始觉得头大了。

好了,你可以用笔或者计算器算下。这个数是0b0000 0011 1000 0000 0000 0000 1111 1000 = 0x038000f8。

我们来利用二进制构造。

bit3~bit7:以bit0为基准构造结果为0x1f。

bit23~bit25:以bit0为基准构造结果为0x07。

开始移位相或:(0x1f<<3) | (0x07<<23)

对比:假如要用C语言定义该数,如下所示。

int a = 0x038000f8;
int a = (0x1f<<3) | (0x07<<23);

很显然,第二个可读性和可塑性提高了很多!

2.4.2 结合位取反获取特定位为0的二进制数

这次我们要获取bit4~bit10为0(该数总共32bit),其余位全部为1的数。有了上面的思维之后,想想该怎么做?我想如果你有了上面的思维后,相信聪明的你已经知道解法了吧。

分析:bit4~bit10为0,说明bit31~bit11都为1,bit3~bit0也都为1。
   bit31~bit11:以bit0为基准构造结果为0x1fffff。
   bit3~bit0:以bit0为基准构造结果为0x0f。

所以,结果是(0x1fffff<<11) | (0x0f<<0)。

但是,你有没有发现采用这种方法并没有什么太大的优势。连续为1的位数太多了,这个数字本身就很难构造,所以这种方法的优势损失掉了。这种特定位(比较少)为0而其余位(大部分)为1的数,不适合用很多个连续1左移的方式来构造,而适合左移加位取反的方式来构造。

思路:先试图构造出这个数的反码,再取反得到这个数。例如本例中要构造的数bit4~bit10为0,其余位为1,那我们就先构造一个bit4~bit10为1,其余位为0的数,然后对这个数按位取反即可。

· 构造该数的反码
bit4~bit10为0的数。其反码为bit4~bit10为1,其余bit为0,这个就很容易构造,就是0x7f<<4。

· 对其取反
对其构造的反码进行取反:~(0x7f<<4)。

对比:对该数用C语言定义,效果很明显。

int a = 0x1fffff<<11) | (0x0f<<0);
int a = ~(0x7f<<4);

2.4.3 总结

位与、位或结合特定二进制数,即可完成寄存器位操作需求。

如果你要的这个数中比较少位为1,大部分位为0,则可以通过连续很多个1左移n位得到。

如果你想要的数中比较少位为0,大部分位为1,则可以通过先构建其位反码,然后再位取反来得到。

如果你想要的数中连续1(连续0)的部分不止一个,那么可以通过多段分别构造,然后再彼此位或即可。这时候因为参与位或运算的各个数为1的位是不重复的,所以这时候的位或其实相当于几个数的叠加。

《嵌入式Linux与物联网软件开发——C语言内核深度解析》一2.4 位运算构建特定二进制数...相关推荐

  1. 《嵌入式Linux与物联网软件开发——C语言内核深度解析》一第1章 C语言与内存1.1 引言...

    本节书摘来自异步社区<嵌入式Linux与物联网软件开发--C语言内核深度解析>一书中的第1章,第1.1节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区"华章计算机&quo ...

  2. 嵌入式Linux与物联网软件开发:C语言内核深度解析

    嵌入式Linux与物联网软件开发:C语言内核深度解析     1.C语言与内存         1.引言         2.计算机程序运行的目的         3.位.半字.字的概念和内存位宽   ...

  3. 嵌入式 Linux 与物联网软件开发 ——C 语言内核深度解析

    C 语言是嵌入式 Linux 领域的主要开发语言. 对于学习嵌入式.单片机.Linux 驱动开发等技术来说,C 语言是必须要过的一关.C 语言学习的特点是入门容易.深入理解难.精通更是难上加难.很多用 ...

  4. 《C语言内核深度解析》——笔记及拓展(1)

    文章是我前几天读了朱有鹏,张先凤老师的<嵌入式Linux与物联网软件开发:C语言内核深度解析>写的,拜读之后,虽没有醍醐灌顶,至少解开了我之前的一些疑惑. <嵌入式Linux与物联网 ...

  5. C语言用位运算构建特定的二进制数

    用位运算构建特定的二进制数 寄存器操作需要给特定位给特定值 使用移位获取特定位为1的二进制数 结合位取反获取特定位为0的二进制数 寄存器操作需要给特定位给特定值 (1)对寄存器特定位进行置1或者清0或 ...

  6. 嵌入式Linux搭建物联网网关,基于嵌入式Linux的物联网网关研究与实现

    摘要: 随着物联网发展速度日益加快,作为连接感知网络和传统通信网络的物联网网关正在其中扮演着重要角色.然而,目前针对物联网网关的统一标准尚未制定,物联网网关的设备类型千差万别.人们往往针对某一具体应用 ...

  7. 如何选择物联网软件开发供应商

    简介: 数以千计的物联网软件开发供应商形成了混乱的生态系统市场.您怎么知道哪个适合您的业务解决方案? 数以千计的物联网软件开发供应商今天已经刺激了市场增长.但与此同时,过度繁荣也令人困惑.它包括云平台 ...

  8. @程序员,物联网软件开发不得不克服的七大挑战

    物联网软件开发是个雷区.市场需要高质量.具有可扩展性.强大.安全且人性化的解决方案,为了将所有风险都考虑在内,物联网开发团队必须重新评估程序和工作流程.本文列出了物联网软件开发项目所面临的七大挑战. ...

  9. Linux学习之嵌入式Linux编程文件IO(C语言版)

    Linux学习之嵌入式Linux编程文件IO(C语言版) 一.文件IO常用函数 1.open 2.write 3.read 示例代码: #include <sys/types.h> #in ...

最新文章

  1. 静态路由中使用一跳和出接口的区别
  2. django部署iiswin10_基于Windows平台的Django在本地部署和腾讯云服务器上部署的方法教程(一)...
  3. zap支持php,golang的zap怎么使用
  4. Android 利用addView 动态给Activity添加View组件
  5. 一文入门 Kafka
  6. vue个人博客项目部署上线
  7. windows下的Zcash钱包(ZEC钱包)-zcash4win 1.0.11
  8. 《Python程序设计实验指导书》81个实验项目选做参考
  9. Win系统 - BIOS设置中找不到U盘选项该怎么办?
  10. 队列等待之enq: TX - row lock contention
  11. 2022还在为怎样去提升自己Android技术而发愁吗?享学课堂是个不错的选择
  12. ibooks打开iframe引用的html文件乱码
  13. !终端伪装测试之fuck校园网
  14. MySQL:开窗函数
  15. 深深的码丨Java NIO 透析
  16. 腾讯云服务器远程连接登录流程
  17. 2018年5月英语--停停走走
  18. 【OpenAirInterface】分立部署核心网与容器化ueransim仿真基站
  19. 什么才是用户的真实需求?
  20. mysql 删除表数据_主外键关联表的数据删除策略

热门文章

  1. Springboot使用thymeleaf进行页面跳转
  2. Ubuntu: ldconfig(解决*.so不是符号连接)
  3. 强网杯Web部分review
  4. 对于redis底层框架的理解(一)
  5. ext3文件系统反删除利器ext3grep应用实战
  6. Android中加载事件的方式
  7. 6月第1周全球域名注册商(国际域名)新增注册量TOP15
  8. project-population
  9. 成为一个拥有优势的人(转)
  10. kafka报错与调试技巧