關於C移位操作

2021-09-30 20:18:35 字數 2315 閱讀 4804

在x86_64平台上,下面這段**輸出的結果是否相同?

#include #include int main(int argc, char* ar**)
輸出結果:

r0 = 144115188075855872, r1 = 33554432

原因:相關彙編**

0000000000400530 :

400530: 55 push %rbp

400531: 48 89 e5 mov %rsp,%rbp

400534: 48 83 ec 30 sub $0x30,%rsp

400538: 89 7d dc mov %edi,-0x24(%rbp)

40053b: 48 89 75 d0 mov %rsi,-0x30(%rbp)

40053f: c7 45 fc 39 00 00 00 movl $0x39,-0x4(%rbp)

400546: 48 c7 45 f0 01 00 00 movq $0x1,-0x10(%rbp)

40054d: 00

40054e: 8b 45 fc mov -0x4(%rbp),%eax

400551: 48 8b 55 f0 mov -0x10(%rbp),%rdx

400555: 89 c1 mov %eax,%ecx

400557: 48 d3 e2 shl %cl,%rdx

40055a: 48 89 d0 mov %rdx,%rax

40055d: 48 89 45 e8 mov %rax,-0x18(%rbp)

400561: 8b 45 fc mov -0x4(%rbp),%eax

400564: ba 01 00 00 00 mov $0x1,%edx

400569: 89 c1 mov %eax,%ecx

40056b: d3 e2 shl %cl,%edx

40056d: 89 d0 mov %edx,%eax

40056f: 48 98 cltq

400571: 48 89 45 e0 mov %rax,-0x20(%rbp)

400575: 48 8b 55 e0 mov -0x20(%rbp),%rdx

400579: 48 8b 45 e8 mov -0x18(%rbp),%rax

40057d: 48 89 c6 mov %rax,%rsi

400580: bf 30 06 40 00 mov $0x400630,%edi

400585: b8 00 00 00 00 mov $0x0,%eax

40058a: e8 81 fe ff ff callq 400410

從彙編**上可以看到,對於第一條位移語句,使用的是暫存器%rdx(64位)儲存位移結果;而第二條位移語句,使用暫存器%edx(32位)儲存位移結果,然後再通過cltq指令,將結果擴充套件到64位。

因為對於32位的數字移57位會發生溢位

實際%edx儲存值為((uint64_t)1 << 57) % ((2^32)-1) = 144115188075855872 % 4294967295 = 33554432

cltq r[%rax ] <- signextend(r[%eax]) convert %eax to quad word,將$eax轉化為8字,即%rax。

cltq是有符號數的擴充套件,如果%eax的最高的32位為1的話,剛%eax的高32擴充套件後全為1;相反如果%eax的高位為0的話,則擴充套件出來後全為0。

關於移位操作

左移 不管是有符號數還是無符號數,數字都往左移動n位,右邊用0補足。如果左移的位數超過整數本身的位數,結果不知道。vs上測試結果是從頭開始。例子 vs,32位機器 int型別,原始值0x1,左移31位後是0x80000000。左移32位後是0x1。原始值0x11,左移31位後是0x80000000,...

c中的移位操作

位移位運算子是將資料看成二進位制數,對其進行向左或向右移動若干位的運算。位移位運算子分為左移和右移兩種,均為雙目運算子。第一運算物件是移位物件,第二個運算物件是所移的二進位制位數。位移位運算子的運算物件 運算規則與結果 結合性如表2 16所示。移位時,移出的位數全部丟棄,移出的空位補入的數與左移還是...

c語言的移位操作

左移時總是移位和補零。右移時無符號數是移位和補零,此時稱為邏輯右移 而有符號數大多數情況下是移位和補最左邊的位 也就是補最高有效位 移幾位就補幾位,此時稱為算術右移。include using namespace std void main buf 1 temp 0x00ff temp temp 8...