2011-04-07 35 views
1

讓我們有一個任務,在變量a上執行左位按位旋轉,而不用C++進位。我認爲,使用assembly inline來執行這個例程會好得多,不是嗎?向左按位旋轉變量沒有進位?

例如,如果我們有a == 100 == 0b<a bunch of zeros>1100100,a LR 1應該提供0b1001001 == 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'將映射到您可以編寫的完全相同的程序集(或者至少等效的程序集 - 例如寄存器可能不同)。 – 2011-04-07 20:39:35

+0

您想繼續在哪裏使用?你的樣品只有很長的一段時間。如果這是你的意思 – sehe 2011-04-07 20:39:55

+0

我認爲現有的轉變是不攜帶的,一個<< 1將自動轉移到城市生活垃圾? – Puppy 2011-04-07 20:41:42

回答

3

隨着高級語言(甚至C語言),隨身攜帶是沒有意義的,因爲沒有辦法從這些語言中讀取進位標誌(以前稱爲高位),除了更多的內聯彙編。另一方面,如果您將高位存儲到另一個變量(並執行移位操作),編譯器可能會生成一個帶進位的移位,然後是進位移位或mov-carry,以便在那裏得到它。編譯器在將兩條指令組合成乘加加法融合指令方面也很合理。


看你的修訂問題,您要執行的操作是完全無關的任何共同的處理器可移用攜帶的指令。由於您想要移位一位,然後清除最重要的一位,您可能會發現bsr指令很有用,許多編譯器有intrinsic functions,可讓您從C代碼中訪問此指令。

3

這樣做內聯彙編做一些簡單的事情就像左移帶進一樣簡單。任何現代編譯器都可以很容易地處理它,並生成與您手寫的任何東西相同的程序集,並且還具有不依賴於平臺的優勢。

1

如果你真的想要彙編器,那麼這裏是如何旋轉左64位變量一位可能看起來在Visual C++中(對於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; 
}