2011-04-07 9 views
1

変数aの左ビットワイドローテーションをC++でのキャリーなしに行う作業をしましょう。私は、このルーチンを実行するためにアセンブリをインラインで使用するほうがはるかに良いと思いますか?キャリーなしで変数にビット単位の回転を残しましたか?

たとえば、a == 100 == 0b<a bunch of zeros>1100100の場合、a LR 10b1001001 == 73(つまり、0b11001000 == 200ではない)を指定する必要があります。

したがって、質問はです:上記の作業に合わせて以下のコードをどのように書き換えるべきですか?

#include <stdio.h> 

int main() 
{ 
    long long a = 0; 

    scanf("%ld", &a); 

    // Here the left-shifting should be replaced with left-rotating 
    printf("%ld\n", a << 1); 

    return 0; 
} 
+0

ほぼ確実にそれほど良くないでしょう。 'a << 1'はあなたが書くことができる全く同じアセンブリにマップされます(または、少なくとも同等のアセンブリ - 例えばレジスタが異なるかもしれません)。 –

+0

どこに持ち越したいですか?あなたのサンプルはちょうど長い長いです。それが意味するものなら、<< 1は自動的にMSWに引き継がれます – sehe

+0

私は既存のシフトが持ち運びではないと思いましたか? – Puppy

答えて

3

高水準言語(Cでも)では、より多くのインラインアセンブリを除き、そのような言語からキャリーフラグ(以前は上位ビット)を読み取る方法がないため、桁上がりは無意味です。

一方、上位ビットを別の変数に格納すると(シフト操作も行う)、コンパイラはshift-with-carryとそれに続くadd-carryまたはmov-carryを生成してそこに取得します。コンパイラは、2つの命令を積和加算命令に組み合わせることも合理的に優れています。あなたの改訂質問を見てみると


、あなたが実行しようとしている操作は、一般的なプロセッサで利用可能なシフト付きキャリー命令とは全く無関係です。 1つずつシフトしてから最上位の1ビットをクリアしたいので、bsr命令が役に立ちます。多くのコンパイラにはintrinsic functionsがあり、Cコード内からこの命令にアクセスできます。

3

キャリー付きの左シフトと同じような簡単な操作を行うには、インラインアセンブリを行う方がよいとは限りません。現代のコンパイラは、それを簡単に処理し、手作業で作成したものと同等のアセンブリを生成します。また、プラットフォームに依存しないという利点もあります。

1

アセンブラが本当に必要な場合は、Visual C++で1ビット左に64ビットの変数を回転させる方法があります(GCC __asmが異なる場合)。比較のために、C++での実装もあります。もちろんこれは32ビットのアセンブラです。

unsigned long long rotate_left_64(unsigned long long n) 
{ 
    return (n << 1) | (n >> 63); 
} 

int main() 
{ 
    unsigned long long a = 0xF0F0F0F0F0F0F0F0; 

    std::cout << std::hex << rotate_left_64(a) << std::endl; 

    __asm 
    { 
     lea ebx, a 
     rol DWORD PTR [ebx], 1 
     rcl DWORD PTR [ebx+4], 1 
    } 
    std::cout << std::hex << a << std::endl; 
    return 0; 
} 
関連する問題