var = (var << shift) | (var >> (sizeof(var)*CHAR_BIT-shift))
このコードを使用しないでください。 shift
が0の場合、動作は未定義です。インテルのICCは、未定義の動作を含む文を削除します。私は最初の手を知っている。
さらに、コードはClangまたはGCCのUndefined Behaviorサニタイザを渡しません。読書については、ClangのControlling Code GenerationまたはGCCのUndefined Behavior Sanitizer – ubsanを参照してください。
私が手にエラーがある:あなたは2つのツールのいずれかを使用している未知のサイズの接尾辞
と命令ニーモニックの
不明使用 - GCCやクランのいずれか。私はAppleがXcode 4の周りにデフォルトでClangに切り詰めると思うので、おそらくあなたはClangを使用しているだろう。
GCCはGNU AS(GAS)に委任し、Clangは統合アセンブラを使用します。どちらの場合も、インテルアセンブリのClangサポートには問題があるため、AT & Tインラインアセンブリを使用する必要があります。たとえば、Clang can't generate a negate instructions(a.k.a. LLVM Bug 24232)です。
Clangを使用する場合は、オペランドサイズを指定する必要があります。したがって、rolb
、rolw
、roll
、およびrolq
とお友達を使用します。これはClangのLanguage Compatibility | Inline Assemblyページに記載されています。
// Immediate
inline word8 rotlImmediate8 (word8 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rolb %1, %0" : "+mq" (x) : "I" ((unsigned char)y));
return x;
}
// Immediate or register
inline word8 rotl8 (word8 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rolb %1, %0" : "+mq" (x) : "cI" ((unsigned char)y));
return x;
}
// Immediate
inline word8 rotrImmediate8 (word8 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorb %1, %0" : "+mq" (x) : "I" ((unsigned char)y));
return x;
}
// Immediate or register
inline word8 rotr8 (word8 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorb %1, %0" : "+mq" (x) : "cI" ((unsigned char)y));
return x;
}
8ビットワードが制約に特別な処理を必要とします:
は、ここのような8ビットの回転が見えるものです。 +g
は使用できません。むしろ+mq
が必要です。ここで
は、16ビット・ワードのバージョンです:
// Immediate
inline word16 rotlImmediate16 (word16 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rolw %1, %0" : "+g" (x) : "I" ((unsigned char)y));
return x;
}
// Immediate or register
inline word16 rotl16 (word16 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rolw %1, %0" : "+g" (x) : "cI" ((unsigned char)y));
return x;
}
// Immediate
inline word16 rotrImmediate16 (word16 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorw %1, %0" : "+g" (x) : "I" ((unsigned char)y));
return x;
}
// Immediate or register
inline word16 rotr16 (word16 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorw %1, %0" : "+g" (x) : "cI" ((unsigned char)y));
return x;
}
そして、ここでは32ビット版です:
// Immediate
inline word32 rotlImmediate32 (word32 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("roll %1, %0" : "+g" (x) : "I" ((unsigned char)y));
return x;
}
// Immediate or register
inline word32 rotl32 (word32 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("roll %1, %0" : "+g" (x) : "cI" ((unsigned char)y));
return x;
}
// Immediate
inline word32 rotrImmediate32 (word32 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorl %1, %0" : "+g" (x) : "I" ((unsigned char)y));
return x;
}
// Immediate or register
inline word32 rotr32 (word32 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorl %1, %0" : "+g" (x) : "cI" ((unsigned char)y));
return x;
}
最後に、ここでは64ビット版です。あなたは__amd64
または__x86_64__
のようなものでそれを守るべきです。回転量は[0,63]
になる可能性があるため、J
という制約を使用します。
// Immediate
inline word64 rotlImmediate64 (word64 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rolq %1, %0" : "+g" (x) : "J" ((unsigned char)y));
return x;
}
// Immediate or register
inline word64 rotl64 (word64 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rolq %1, %0" : "+g" (x) : "cJ" ((unsigned char)y));
return x;
}
// Immediate
inline word64 rotrImmediate64 (word64 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorq %1, %0" : "+g" (x) : "J" ((unsigned char)y));
return x;
}
// Immediate or register
inline word64 rotr64 (word64 x /*value*/, unsigned int y /*rotate*/)
{
__asm__ ("rorq %1, %0" : "+g" (x) : "cJ" ((unsigned char)y));
return x;
}
ClangはGCCのような定数を伝播しないので、Immediate-8バージョンの回転に問題が生じる可能性があります。 Stack OverflowのForce Clang to “perform math early” on constant valuesとLLVM Bug 24226を参照してください。
時間を取って、John RegehrのSafe, Efficient, and Portable Rotate in C/C++にアクセスしてください。そのような反楽観主義のようなものです。これは、C/C++で回転を正しく書くと(つまり、未定義の振る舞いがなくなると)回転として認識されなくなり、回転命令はになりません。
最後に、スタックオーバーフローに関するNear constant time rotate that does not violate the standardsも参照してください。
本当に組み立てが必要ですか?これがパフォーマンスのボトルネックである場合にのみ必要です。通常の使用では、 'var =(var << shift)| (var >>(sizeof(var)* 8-shift)) 'となります。 – Dave
詳細については、http://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts – Dave
nice。ご返信ありがとうございます。これが質問に答えるので、あなたが答えを出すなら、私はそれを受け入れます。 –