1

我正在查看 NIC 的数据表规范,它说:

寄存器的位 2:3 包含 NIC 速度,4 包含链接状态等。如何使用按位隔离这些位?

例如,我已经看到了隔离链接状态的代码,类似于:

(link_reg & (1 << 4))>>4

但我不太明白为什么正确的转变。我必须说,我仍然对按位运算不太满意,即使我了解如何转换为二进制以及每个操作的作用,但它并不实用。

4

5 回答 5

2

这取决于你想用那个位做什么。链接状态,称之为 L 在某处的变量/寄存器中

    43210
xxxxLxxxx

要使用 1 隔离您想要的那个位,按位运算:

  xxLxxxx
& 0010000
=========
  00L0000

1<<4 = 1 有 4 个零或 0b10000,你想要的数字。

status&(1<<4) 

这将给出零或 0b10000 的结果。您可以进行布尔比较以确定它是假(零)还是真(非零)

if(status&(1<<4))
{
   //bit was on/one
}
else
{
   //bit was off/zero
}

如果您希望结果为 1 或零,则需要将结果移至个列

  (0b00L0000 >> 4) = 0b0000L

如果 and 的结果为零,则移位仍然为零,如果结果为 0b10000,则右移 4 给出 0b00001

所以

(status&(1<<4))>>4 gives either a 1 or 0;

(xxxxLxxxx & (00001<<4))>>4 =
(xxxxLxxxx & (10000))>>4 = 
(0000L0000) >> 4 = 
0000L

另一种使用更少操作的方法是

(status>>4)&1;
xxxxLxxxx >> 4 = xxxxxxL
xxxxxxL & 00001 = 00000L
于 2012-10-17T03:45:05.453 回答
1

最容易看一些二进制数。

这是一个可能的寄存器值,下面是位索引:

  00111010
  76543210

所以,第 4 位是 1。我们如何得到那个位?我们构造一个仅包含该位的掩码(我们可以通过将 1 移到正确的位置来做到这一点,即1<<4),并使用&

  00111010
& 00010000
----------
  00010000

但我们想要一个 0 或 1。所以,一种方法是将结果向下移动:00010000 >> 4 == 1。另一种选择是!!val,它将 0 变为 0 并将非零变为 1(请注意,这仅适用于单个位,而不是像链接速度这样的两位值)。

现在,如果您想要位 3:2,您可以使用设置了这两个位的掩码。您可以写入3 << 2获取00001100(因为 3 设置了两个位)。然后我们&用它:

  00111010
& 00001100
----------
  00001000

并向下移动 2 以获得10所需的两位。因此,获得两位链接速度的语句将是(link_reg & (3<<2))>>2.

于 2012-10-17T03:35:13.183 回答
0

您可以使用它来确定位置的位pos是否设置在val

#define CHECK_BIT(val, pos) ((val) & (1U<<(pos)))

if (CHECK_BIT(reg, 4)) {
    /* bit 4 is set */
}

如果两个操作数的相应位设置为 1,则按位与运算符 (&) 将结果中的每个位设置为 1。否则,结果位为 0。

于 2012-10-17T03:32:45.090 回答
0

如果您想将第 2 位和第 3 位(从 0 开始计数)视为一个数字,您可以这样做:

unsigned int n = (link_get & 0xF) >> 2;

按位加 15(二进制为 0b1111)将除底部四位以外的所有位设置为零,然后右移 2 位得到第 2 位和第 3 位中的数字。

于 2012-10-17T03:35:19.970 回答
0

问题是隔离位是不够的:您需要移动它们以获得正确的值大小顺序。

在您的示例中,您的大小为 2 位和 3 位(我假设最低有效位为 0 位),这意味着它是 [0,3] 范围内的值。reg & (0x03<<2)现在您可以使用or, 转换来屏蔽这些位,(reg & 0x12)但这还不够:

reg   0110 1010 &
0x12  0000 1100
---------------
0x08  0000 1000

如您所见,结果1000b是 8,超出范围。要解决这个问题,您需要将结果移回,以便您感兴趣的值的最低有效位对应于包含字节的最低有效位:

0000 1000 >> 2 = 10b = 3

现在是正确的。

于 2012-10-17T03:36:29.330 回答