Cで暗号関係のコードを書いていた。このテのコードではビット操作が少なからずある。Cの演算子にはビットシフトはあるが、回転は無い。いろいろ組み合わせて書けなくはないが、インラインアセンブラを使うことにした。速度面で多少なりとも有利になることも期待している。それで出来たのが以下だ。
static inline uint32_t rotl(uint32_t src, uint8_t n) { uint32_t result; __asm__("roll %2,%1" : "=r"(result) : "0"(src), "c"(n)); return result; }
これはgcc(Mingw版)用のコードである。gccの場合はインラインアセンブラを使った部分も最適化の対象になるので、意図通りのふるまいを得たければちょっと面倒な指定が必要になる。ここでは結果の出力先は自動、但し入力元と同じレジスタであること、そして回転させるビット数を入れるレジスタはECXであることを指定している。(実際には回転数にはECXの下位5ビット分しか使われないが、仮にECX全体が使われたとしても結果が同じになることは自明である。)
これにより、命令一個で回転が完了する。というわけではない。何故なら回転数を入れるレジスタとしてECXを指定しているからだ。nが定数の場合であっても常に一旦ECXに入れるという操作が入る。定数の場合には即値(immediate)にしたいと思うのだけれど、どういう方法が有るだろうか?