2017-12-27 1233 views
0

我想寫使用內聯彙編用C離開操作的旋轉,像這樣:8位內聯彙編大小不匹配旋轉

byte rotate_left(byte a) { 
    __asm__("rol %0, $1": "=a" (a) : "a" (a)); 
    return a; 
} 

(凡字節通過typedef unsigned char型)。

這就提出了一個錯誤

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

有什麼問題嗎?

+1

你在哪裏定義'byte'? – klutt

+0

使用AT&T語法,src和destination是相反的。也許你的意思是'「rol $ 1,%0」' –

+1

https://godbolt.org/g/z6Qof7這裏沒有必要內聯彙編(至少對於gcc和clang) –

回答

3

AT & T語法使用與Intel語法相反的順序。旋轉次數必須是第一次,而不是最後一次:rol $1, %0


而且,你不需要和不應該使用內聯彙編本:https://gcc.gnu.org/wiki/DontUseInlineAsm

Best practices for circular shift (rotate) operations in C++描述,GNU C有狹窄的旋轉內部函數,因爲旋轉,慣用語法識別代碼失敗優化掉旋轉計數的and。即使對於8位和16位,x86移位/旋轉掩碼的計數也爲count & 31,但旋轉仍然環繞。儘管如此,換班確實很重要。

無論如何,gcc有一個內置函數用於縮小旋轉以避免任何開銷。在x86intrin.h中有一個__rolb包裝,但MSVC使用其自己的__rotr8等等intrin.h。無論如何,clang不支持__builtinx86intrin.h旋轉包裝,但gcc和ICC都支持。

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

我用uint8_tstdint.h像正常人代替限定byte類型。

這並不能編譯鏗鏘,但it compiles as you'd hope with gcc7.2

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

這使您儘可能高效編譯爲您的內聯彙編都做不到的功能,但它可以完全優化掉了編譯時常量,並且編譯器知道它是如何工作的以及它做了什麼並且可以相應地進行優化。

+0

如上所述,gcc [確實似乎認識到一個天真的旋轉](https://godbolt.org/g/z6Qof7),所以它甚至不需要使用任何內在的;但很奇怪,VC++和icc都無法識別它。 –

+0

@MatteoItalia:它可以識別它,但很難讓它在沒有'和'的情況下只發布'rolb'來屏蔽運行時變量計數。在成語識別器可以處理字節和16位旋轉之前,可能已經添加了內建函數;我沒有檢查舊的gcc版本。 –

+0

更新:VC++ [確認它](https://godbolt.org/g/fSn6YK)如果我添加一些強制轉換爲'uint8_t'(即使只是左邊的一個似乎工作正常)。 –