Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 按位-如何实现位掩码操作? 上下文_C_Assembly_Bitmask - Fatal编程技术网

C 按位-如何实现位掩码操作? 上下文

C 按位-如何实现位掩码操作? 上下文,c,assembly,bitmask,C,Assembly,Bitmask,我使用了很多位操作,但我甚至不知道它们是如何在尽可能低的级别上实现的 我想看看intel/amd开发人员如何实现这些操作。如果不在我的代码中替换它们,那将是愚蠢的。。但是为了更广泛地了解正在发生的事情 我试图找到一些信息,但大多数时候,人们会询问它的用途,或者用其他按位操作替换它,但这里的情况并非如此 问题 它是否在32位上进行汇编(sse)中的基本迭代并进行比较 有什么窍门可以让它加速吗 多亏了大多数都直接在CPU上实现,作为基本的本机指令,而不是SSE的一部分。这些是CPU寄存器上最古老、最

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

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

我试图找到一些信息,但大多数时候,人们会询问它的用途,或者用其他按位操作替换它,但这里的情况并非如此

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

有什么窍门可以让它加速吗


多亏了

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

至于如何实现
异或
等,如果您确实感兴趣,请查阅数字逻辑设计或离散数学。查找触发器、AND门或NAND/NOR/XOR门

此外,还可以查找K映射(卡诺映射),这些是可以用来手动实现逻辑电路的

如果你真的喜欢阅读,你可以报名参加数字逻辑设计课程,如果你有机会进入工程或计算机科学大学。你可以在试验板上用大型集成电路来构建逻辑电路,但现在大多数CPU都是用代码“编写”的,就像软件一样,并“打印”在硅片上

由于功能的完整性,
NAND
NOR
尤其令人感兴趣(您可以使用NAND或NOR构建任何真值表)

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

您可以用NAND重写任何逻辑


正如您也可以看到的,它非常有效,您无法获得比使用二进制的单个门更低的电平(尽管有三元/三态逻辑),因此它是单时钟状态更改。所以对于64位CPU寄存器,每个寄存器需要64个这样的婴儿并排出现。。。每个核心。。。根据指令。这只是“逻辑”寄存器。因为高级处理器(如Intel Core)进行寄存器重命名,所以硅中的物理寄存器比逻辑上可用的名称要多。

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

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


一些旧处理器中的位移位可能涉及单移位循环。也就是说,
1正如您所知,计算机中的数据是以二进制格式表示的

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

然而,对于基本操作,计算机需要知道您处理了多少数据。典型的整数大小是32位。因此,它不仅仅是
1101b
,它是
0000000000000000000000000000 1101b
——32位,其中大部分未使用

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

12位和7是多少?(在C语言中,
12和7

为什么??垂直思考!看左边的一组数字——1和0是0。那么,0和1是0。那么,1和1是1。最后,0和1是0

这是基于和真值表,该表声明了这些规则——只有true(aka 1)和true(aka 1)会导致false(aka 0)。所有其他结果值均为false(也称为0)

同样地,
真值表表明,除false(aka 0)和false(aka 0)外,所有结果均为真(aka 1),这导致false(aka 0)

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

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

~7

但是等等。。那些前导零呢?嗯,是的,在我因为它们不重要而忽略它们之前,但现在它们肯定是:

00000000000000000000000000000111b ~7
---------------------------------  =
11111111111111111111111111111000b  ... big number?
如果您指示计算机将结果视为无符号整数(32位),这是一个非常大的数字。(略低于40亿)。如果您指示计算机将结果视为带符号整数(32位),则为-8

正如您可能已经猜到的,由于所有这些操作的逻辑都非常简单,因此您无法做太多的事情来加快它们的速度。但是,位操作遵循与布尔逻辑相同的逻辑,因此可以使用布尔逻辑缩减技术来减少可能需要的位操作数

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

然而,这是一个非常复杂的问题
1010b 12 &
0111b  7
-----  =
0010n  2
1010b 12 |
0111b  7
-----  =
1111n 15
0111b ~7
-----  =
1000b  8
00000000000000000000000000000111b ~7
---------------------------------  =
11111111111111111111111111111000b  ... big number?