1

NIC のデータシート仕様を見ていると、次のように書かれています。

レジスタのビット 2:3 には NIC 速度が含まれ、4 にはリンク状態などが含まれます。これらのビットをビットごとに分離するにはどうすればよいですか?

たとえば、次のようなリンク状態を分離するコードを見てきました。

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

しかし、なぜ右シフトなのかよくわかりません。バイナリに変換する方法と各操作が何をするかは理解していますが、ビットごとの操作にはまだかなり慣れていませんが、実用的ではありません。

4

5 に答える 5

2

それは、そのビットで何をしたいかによって異なります。リンク状態、それを呼び出します L は変数/レジスタのどこかにあります

    43210
xxxxLxxxx

必要なビットを 1 で分離するには、ビットごとの操作を行います。

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

1<<4 = 4 つのゼロまたは 0b10000 を含む 1、必要な数。

status&(1<<4) 

これにより、ゼロまたは 0b10000 のいずれかの結果が得られます。ブール比較を実行して、false (ゼロ) か true (ゼロではない) かを判断できます。

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

結果を 1 または 0 にしたい場合は、結果を 1 列にシフトする必要があります。

  (0b00L0000 >> 4) = 0b0000L

and の結果が 0 の場合、シフトしても 0 になります。結果が 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

いくつかの 2 進数を見るのが最も簡単です。

以下は可能なレジスタ値で、下にビット インデックスがあります。

  00111010
  76543210

つまり、ビット 4 は 1 です。そのビットを取得するにはどうすればよいでしょうか。そのビットのみを含むマスクを作成し(これは、1 を適切な場所にシフトすることで実行できます。つまり、1<<4)、次を使用します&

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

ただし、0 または 1 が必要です。したがって、1 つの方法は、結果を下にシフトすることです00010000 >> 4 == 1。別の代替手段は!!valで、0 を 0 に、ゼロ以外を 1 に変換します (これは、リンク速度のような 2 ビット値ではなく、1 ビットに対してのみ機能することに注意してください)。

ここで、ビット 3:2 が必要な場合は、両方のビットが設定されたマスクを使用できます。3 << 2get に書き込むことができます00001100(3 には 2 つのビットが設定されているため)。次に、それを&使用します。

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

を 2 だけ下にシフトして10、目的の 2 ビットを取得します。したがって、2 ビットのリンク速度を取得するステートメントは(link_reg & (3<<2))>>2.

于 2012-10-17T03:35:13.183 に答える
0

問題は、ビットを分離するだけでは十分ではないということです。値の正しいサイズの順序を取得するには、ビットをシフトする必要があります。

あなたの例では、サイズにビット 2 と 3 があります (最下位はビット 0 であると想定しています)。これは、[0,3] の範囲の値であることを意味します。reg & (0x03<<2)これらのビットをor でマスクして変換できるようになり(reg & 0x12)ましたが、これでは十分ではありません。

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

ご覧のとおり、結果は1000b8 で、範囲を超えています。これを解決するには、関心のある値の最下位ビットが含まれているバイトの最下位ビットに対応するように、結果をシフトバックする必要があります。

0000 1000 >> 2 = 10b = 3

これは正しいです。

于 2012-10-17T03:36:29.330 に答える
0

これを使用して、位置のビットposが設定されているかどうかを判断できvalます。

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

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

ビット演算 AND 演算子 (&) は、両方のオペランドの対応するビットが 1 に設定されている場合、結果の各ビットを 1 に設定します。それ以外の場合、結果のビットは 0 です。

于 2012-10-17T03:32:45.090 に答える
0

ビット 2 と 3 (カウントは 0 から開始) を数値として扱いたい場合は、次のようにします。

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

ビットごとの and with 15 (バイナリでは 0b1111) は、下位 4 ビットを除くすべてをゼロに設定し、次の 2 による右シフトは、ビット 2 と 3 の数値を取得します。

于 2012-10-17T03:35:19.970 に答える