2016-12-14 90 views
0

在C++函數,我有下列變量:奇怪的位操作導致C++ /反彙編?

uint32_t buf = 229; //Member variable 
int bufSize = 0;  //Member variable 
static constexpr const uint32_t all1 = ~((uint32_t)0); 

這行代碼:

uint32_t result = buf & (all1 >> (32-bufSize)); 

接着的result值是229,兩者均由控制檯輸出,或通過與調試GDB。期望值當然是0,並且任何試圖重現問題的最小例子都失敗了。

所以我去了反彙編並一步一步地執行它。比特移位操作是在這裏:

0x44c89e <+0x00b4>  41 d3 e8     shr %cl,%r8d 

調試寄存器表明指令之前,rcx=0x20r8=0xFFFFFFFF

的指令後,我們仍然有r8=0xFFFFFFFF

我有86的一個非常貧困的知識-64程序集,但是這個指令應該是一個無符號的轉換,那麼爲什麼heck不是結果0?

我對編譯器使用MinGW的海灣合作委員會的x86-64 4.9.1

+6

」如果右操作數 爲負數,或者大於或等於升級的左操作數的位長度,則行爲未定義。 (5.8,Shift運算符。) – molbdnilo

+2

對於x86,硬件僅使用cl的低5位作爲移位計數。曾幾何時,減少了中斷延遲。 –

+0

調用 - 在編譯器上啓動,你將有'-Wshift-count-overflow'問題。 – user902384

回答

2

調用-Wall和你正在使用32是unsigned int型的大小換擋,你將有-Wshift-count-overflow問題。現在你只需要做一件事就可以瞭解它。將32更改爲31並編譯。然後比較生成的程序集,你會知道哪裏出了問題。

最簡單的修復方法是使用long數據類型爲all1result。 「

+0

「use'long' data type」 - use'unsigned long'。簽名類型的轉換通常會導致混淆。 –

+0

是的,你想'shr'不是'sar'的確定。 – user902384