*参照元 [#lb6f0e91] #backlinks *説明 [#ff8c41b0] -パス: [[linux-2.6.33/arch/x86/include/asm/bitops.h]] -指定されたビット位置の値をテストする。 --ビット位置が可変(変数など)の場合に使用する。 **引数 [#fb4980d7] -int nr --ビット位置 -volatile const unsigned long *addr --評価対象の unsigned long 値のポインタ **返り値 [#lcee7600] -int --ビットがセットされている場合 -1、ビットがセットされていない場合 0 **参考 [#hf705d6a] *実装 [#m69a8723] static inline int variable_test_bit(int nr, volatile const unsigned long *addr) { int oldbit; asm volatile("bt %2,%1\n\t" "sbb %0,%0" : "=r" (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr)); -1行目: bt にて addr の nr ビット目の値が CF にストアされる。 -2行目: sbb にて %0(oldbit) = %0 - %0 - CF が計算される。 %0 - %0 は当然 0 なので、計算結果は CF のみで決まる。 なぜ sbb 命令かというと、CF フラグを見るための分岐命令を排除するため。 -2行目: sbb にて %0(oldbit を割り当てるレジスタのこと) に %0 - %0 - CF が計算結果が格納される。 %0 - %0 は 0 のため、計算結果は CF のみで決まる。 cmp, jmp, mov でも実現できるが、sbb 命令を使えば CF フラグの結果による分岐命令を排除できるからである。 --CF = 1(ビットが 1 だったとき): %0(oldbit) = -1 --CF = 0(ビットが 0 だったとき): %0(oldbit) = 0 -x86 では有名なハックのようで、おそらく昔はこの方法が速かった(?)のでしょう。 -最近の IA32 アーキテクチャだと sbb 命令は遅いようです。 --[[http://download.intel.com/jp/developer/jpdoc/ia32.pdf]] --[[http://slashdot.jp/~kmra/journal/464748]] return oldbit; } *コメント [#z5166ed3]