按位 - 如何实现位掩码操作?

时间:2014-10-31 16:24:41

标签: c assembly bitmask

上下文

我使用了很多按位操作,但我甚至不知道它们是如何在最低级别实现的。

我想看看intel / amd devs如何实现这些操作。不要在我的代码中替换它们,这将是愚蠢的..但要更广泛地了解正在发生的事情。

我试图找到一些信息,但大多数时候,人们会询问它的用法或用其他按位操作替换它,这不是这里的情况。

问题

它是否在32位的汇编(sse)中进行基本迭代并进行比较?

是否有一些技巧可以加快速度?

由于

4 个答案:

答案 0 :(得分:9)

大多数都直接在CPU上实现,作为基本的本机指令,而不是SSE的一部分。这些是CPU寄存器中最古老,最基本的操作。

如何实施andorxor等,如果您真的感兴趣,请查看数字逻辑设计或离散数学。查找触发器,与门或NAND / NOR / XOR门

https://en.wikipedia.org/wiki/NAND_logic

同样查找K-maps(卡诺图),您可以使用它们来手动实现逻辑电路。

https://en.wikipedia.org/wiki/Karnaugh_map

如果您真的喜欢阅读,如果您有权使用工程或计算机科学大学,您可以注册数字逻辑设计课程。您将在面包板上构建具有大型IC的逻辑电路,但是现在大多数CPU已经被写入"使用代码,如软件,"打印"在硅片上。

特别感兴趣的是NANDNOR,因为它们的功能完整性(您可以使用NAND或NOR来构造任何真值表)。

NAND(逻辑符号看起来像= Do - )

A
  =Do- Q    is Q = NOT(A AND B)
B

Truth table
A    B     Q
0    0     1
0    1     1
1    0     1
1    1     0

你可以用NAND重写任何逻辑。

正如您所看到的,它非常高效,您可以获得比具有二进制的单个门更低的级别(尽管存在三态/三态逻辑),因此其单个时钟状态发生变化。因此,对于64位CPU寄存器,您需要并排64个这样的婴儿,PER寄存器... PER核心... PER指令。这只是"逻辑"寄存器。由于高级处理器(如英特尔酷睿)会注册重命名,因此您在硅片中拥有的物理寄存器数量远远超过您在逻辑上可用的名称。

答案 1 :(得分:4)

AND,OR,XOR和NOT操作在硅片中非常有效地实现,因此在大多数处理器上通常是单周期本机指令。也就是说,对于16位处理器,整个16位寄存器立即进行AND运算;在32位处理器上,一次32位,等等。您可能想要了解的唯一性能问题是 alignment :在ARM处理器上,例如,如果32位值启动在存储器地址是4的倍数时,读取 - 修改 - 写入可以在两个或三个周期内完成。如果它位于奇数地址,则必须在相邻的对齐地址和两次写入时进行两次读取,因此速度较慢。

一些较旧的处理器中的位移可能涉及单个移位的循环。也就是说,1 << 5将花费比1 << 2更长的时间。但是大多数现代处理器都有所谓的“桶形移位器”,可以将所有移位均衡到寄存器大小,因此在Pentium上,1 << 31不会超过1 << 2

加法和减法也是快速原语。乘法和除法很棘手:这些主要是作为微码循环实现的。通过在高端处理器中将环路展开到大块硅片中可以加速乘法,但除法不能,因此通常除法是微处理器中最慢的基本操作。

答案 2 :(得分:1)

按位运算是处理器的组成部分,因此用指令公开这些运算是很自然的。诸如AND,OR,XOR,NOR,NAND和NOT之类的操作可以由ALU执行,每位只有几个逻辑门。重要的是,结果的每一位只依赖于输入的两位(与乘法或加法不同),因此整个操作可以并行进行而不会出现任何复杂情况。

答案 3 :(得分:0)

如您所知,计算机中的数据以二进制格式表示。

例如,如果您有整数13,则表示为1101b(其中b表示二进制)。这与(1) * 8 + (1) * 4 + (0) * 2 + (1) * 1 = 13一致,就像(1) * 10 + (3) * 1 = 13 - 不同的基础。

但是,对于基本操作,计算机需要知道您正在使用多少数据。典型的整数大小是32位。所以它不仅仅是1101b,而是00000000000000000000000000001101b - 32位,其中大多数未被使用。

按位操作就是这样 - 它们只在位级操作。添加,乘法和其他操作一次考虑多个位来执行其功能,但按位运算符则不会。例如:

什么是12位和7? (用C俗语,12 & 7

1010b 12 &
0111b  7
-----  =
0010n  2

为什么呢?垂直思考!看左边的数字--1和0是0.然后,0和1是0.然后,1和1是1.最后,0和1是0.

这是基于声明这些规则的真值表 - 只有true(aka 1)和true(aka 1)才会导致false(也就是0)。所有其他结果值均为假(也称为0)。

同样,or真值表表明所有结果都是真的(也就是1),除了假(又称0)和假(又称为0)导致假(又称为0)。

让我们做同样的例子,但这次让我们的计算机12按位 - 或7.(或用C语言,12 | 7

1010b 12 |
0111b  7
-----  =
1111n 15

最后,让我们考虑另一个主要的按位运算符:不是。这是一个一元的运算符,你只需翻转每一位。让我们按位计算 - 不是7(或用C俗语,~7

0111b ~7
-----  =
1000b  8

但是等等......所有那些领先的零怎么样?嗯,是的,在我省略之前因为它们并不重要,但现在肯定是:

00000000000000000000000000000111b ~7
---------------------------------  =
11111111111111111111111111111000b  ... big number?

如果您指示计算机将结果视为无符号整数(32位),那么这是一个非常大的数字。 (少于40亿)。如果您指示计算机将结果视为有符号整数(32位),即-8。

正如您可能已经猜到的那样,由于逻辑对于所有这些操作来说非常简单,因此您无法更快地使它们单独运行。但是,按位运算遵循与布尔逻辑相同的逻辑,因此您可以使用布尔逻辑简化技术来减少可能需要的按位运算的数量。

e.g。 (A & B) | (A & C)的结果与A & (B | C)

相同

然而,这是一个更大的话题。卡诺图是一种技术,但boolean algebra通常是我在编程时最终使用的。