2017-12-27 26 views
0

を回転させます。インラインアセンブリサイズの不一致は、私はそうのように、インラインアセンブリを使用してCの動作を左回転を記述しようとしています

これは、エラーを発生させ

/tmp/ccKYcEHR.s:363: Error: operand size mismatch for `rol'.

ここでの問題は何ですか?

+1

ここで、「バイト」を定義しますか? – klutt

+0

AT&Tの構文では、srcとdestinationは逆です。たぶんあなたは '' rol $ 1、%0 "' –

+1

https://godbolt.org/g/z6Qof7のためにインラインアセンブルする必要はありません(少なくともgccとclangの場合) –

答えて

3

& T構文では、Intel構文の逆の順序が使用されます。回転数は、最後ではなく、最初でなければなりません:rol $1, %0


また、あなたは必要ありませんし、このためにインラインアセンブラを使用しないでください。https://gcc.gnu.org/wiki/DontUseInlineAsm

Best practices for circular shift (rotate) operations in C++で説明したように回転・イディオム認識コードが失敗したので、GNU Cは、狭い回転のための組み込み関数を持っています回転カウントのandを最適化します。 x86は、8ビットと16ビットの場合でもcount & 31でマスクをシフト/回転しますが、回転はまだ回転します。しかしそれはシフトのために重要です。

とにかく、gccにはオーバーヘッドを避けるための狭回転の組み込み関数があります。 x86intrin.hには__rolbラッパーがありますが、MSVCはそのなどをintrin.hから使用しています。とにかく、clangはローラーの__builtinまたはx86intrin.hラッパーをサポートしていませんが、gccとICCはサポートしていません。

#include <stdint.h> 
uint8_t rotate_left_byte_by1(uint8_t a) { 
    return __builtin_ia32_rolqi(a, 1); // qi = quarter-integer 
} 

私はbyteタイプを定義するのではなく、普通の人のようにstdint.hからuint8_tを使用しました。

これがすべてで打ち鳴らすとコンパイルされませんが、it compiles as you'd hope with gcc7.2

rotate_left_byte_by1: 
    movl %edi, %eax 
    rolb %al 
    ret 

これは、あなたの今までには可能性があなたのインラインアセンブラとして効率的にコンパイル機能が得られますが、これはコンパイル時のために完全に離れて最適化することができますコンパイラはそれがどのように動作するか/それが何をしているかを知っており、それに応じて最適化することができます。

+0

gccは純粋な回転を1つ認識する](https://godbolt.org/g/z6Qof7)ので、組み込み関数を使用する必要はないようです。しかし、VC++とiccの両方がそれを認識できないのは不思議です。 –

+0

@MatteoItalia:それを認識しますが、ランタイム変数のカウントをマスクするために 'と'を使わずに 'rolb'を出すのは難しいです。そしておそらく、イディオムレコグナイザがバイトと16ビットの回転を処理できるようになる前に、ビルトインが追加されました。私は古いgccのバージョンをチェックしませんでした。 –

+0

更新: 'uint8_t'にいくつかのキャストを自由に追加するとVC++ [それを認識できます](https://godbolt.org/g/fSn6YK)(左シフトのものでもうまくいくようです)。 –

関連する問題