在阅读了最新的CodeProject时事通讯之后,我发现了有关按位运算的这篇文章。它使阅读有趣,我当然可以看到检查整数是偶数还是奇数的好处,但是测试是否设置了第n位?这样做的好处可能是什么?
在阅读了最新的CodeProject时事通讯之后,我发现了有关按位运算的这篇文章。它使阅读有趣,我当然可以看到检查整数是偶数还是奇数的好处,但是测试是否设置了第n位?这样做的好处可能是什么?
Answers:
在嵌入式系统中对硬件寄存器进行编程时,按位操作绝对至关重要。例如,我曾经使用过的每个处理器都有一个或多个寄存器(通常是特定的内存地址),用于控制是启用还是禁用中断。要允许中断触发,通常的过程是为该中断类型设置使能位,而最重要的是,不修改寄存器中的任何其他位。
触发中断时,通常会在状态寄存器中设置一个位,以便单个服务例程可以确定中断的确切原因。测试各个位可以快速解码中断源。
在许多嵌入式系统中,可用的总RAM可能是64、128或256个字节(即字节而不是千字节或兆字节)。在这种环境下,通常使用一个字节存储多个数据项,布尔标志等,然后使用位操作设置并阅读这些内容。
多年来,我一直在与卫星通信系统一起工作,该系统的消息有效载荷为10.5字节。为了充分利用此数据包,必须将信息打包到数据块中,而在字段之间不保留任何未使用的位。这意味着广泛使用按位和移位运算符来获取信息值并将其打包到正在传输的有效载荷中。
基本上,出于大小和速度方面的考虑,您会使用它们。按位运算非常简单,因此通常比算术运算快。例如,要获取rgb值的绿色部分,算术方法为(rgb / 256) % 256
。使用按位运算,您将做一些事情(rgb >> 8) & 0xFF
。后者要快得多,一旦您习惯了它,它也会变得更容易。通常,当您需要以紧凑而快速的方式对数据进行编码/解码时,按位运算会发挥很多作用。
BYTE g1 = (rgb / 256) % 256;
00E51013...C1 E9 08...shr ecx,8
00E51016...88 0C 24...mov byte ptr [esp],cl
在为内存或CPU能力受到限制的嵌入式系统进行写操作时,通常会使用此类操作。
例如,为了节省空间,您可以通过使用每个位代表一个布尔值来将多个变量存储在单个8位int变量中。然后,您需要一种快速的方法来设置特定位或检索位值。
通常,当在具有千兆字节内存的台式PC上使用C#等高级语言进行编程时,您实际上并不关心每个bool
字节占用一个字节。但是,如果您正在用C编写具有2kb内存的微控制器,那么每个位都很重要,因此将8个布尔值打包到一个字节中的能力可能至关重要。
[Flags]
允许使用Enum
as位字段的属性。例如,Font
具有一个Style
属性,该属性是一个包含粗体,斜体,下划线和删除线的位字段。
出于与嵌入式电子设备相同的原因,在视频和音频编解码器中还经常使用按位运算。当您要制作超高效的视频编解码器时,能够将五个标志和一个十一位计时器打包为一个int十分有用。
实际上,MPEG 4甚至对可变位长字段使用指数Golomb编码。最后一个数据包的宽度为17或19位,则该数据包的宽度可能仅为3或5位-您可以通过按位运算找出所有内容。
研究过使用逻辑门(或非逻辑门)构建二进制加法器的人可以理解结合了按位逻辑运算,按位移位运算和算术运算的技巧。在那个圈子之外,没有详细的评论很难理解。
在对SIMD单元进行编程时,这很有用,尤其是在CPU的体系结构有意遗漏一些SIMD指令的情况下,因为它们可能会被其他一些模拟。
例如,该体系结构可能没有定义任何指令来获取一组16字节的负值,但是可以通过按位取反然后加1来模拟。第二个操作数的负数。“备用路线”的可用性是省略某些说明的原因。
同样,SIMD可能仅支持并行8位加法,而没有为16位,32位或64位等较宽的元素实现加法。为了模拟它们,需要从8位计算结果中提取符号位,然后对下一个元素执行进位运算。