day2_シフト演算

自分の中でピンとこなかったシリーズなので記事化

 

そもそもシフト演算ってなんだろ、というところから。

シフト演算は掛け算/割り算の代わりに利用すると処理が高速になるとのこと。

 

int Calc() {

	unsigned int a = 10;

	//20
	printf("左シフト : %d\n", a << 1);

	//5
	printf("右シフト : %d\n", a >> 1);

	return 0;

}


逆アセも一緒に見てみた


000A42F0  push        ebp  
000A42F1  mov         ebp,esp  
000A42F3  sub         esp,0D8h  
000A42F9  push        ebx  
000A42FA  push        esi  
000A42FB  push        edi  
000A42FC  lea         edi,[ebp-0D8h]  
000A4302  mov         ecx,36h  
000A4307  mov         eax,0CCCCCCCCh  
000A430C  rep stos    dword ptr es:[edi]  
000A430E  mov         ecx,offset _D0BBC2EA_Source@cpp (0AC003h)  
000A4313  call        @__CheckForDebuggerJustMyCode@4 (0A121Ch)  
000A4318  mov         dword ptr [a],0Ah  
000A431F  mov         eax,dword ptr [a]  
000A4322  shl         eax,1  
000A4324  push        eax  
000A4325  push        offset string "d\n" (0A7BD8h)  
000A432A  call        _printf (0A1046h)  
000A432F  add         esp,8  
000A4332  mov         eax,dword ptr [a]  
000A4335  shr         eax,1  
000A4337  push        eax  
000A4338  push        offset string "\x8d\xb6\x83V\x83t\x83g : %d\n" (0A7BE8h)  
000A433D  call        _printf (0A1046h)  
000A4342  add         esp,8  
000A4345  xor         eax,eax  
000A4347  pop         edi  
000A4348  pop         esi  
000A4349  pop         ebx  
000A434A  add         esp,0D8h  
000A4350  cmp         ebp,esp  
000A4352  call        __RTC_CheckEsp (0A1226h)  
000A4357  mov         esp,ebp  
000A4359  pop         ebp  
000A435A  ret 




なるほど、lとrがleft,rightを示しているっぽい。

1行のニーモニックで処理が完結できることから、処理が高速といわれてるんだろうか。

 

シフト演算なしの乗算/除算を試してみてコードに変化があるか確認してみる。

 

int Calc2() {
    unsigned int a = 10;

    printf("乗算:%d\n", a * 2);
    printf("除算:%d\n", a / 2);

    return 0;
}

 

push        ebp  
006542F1  mov         ebp,esp  
006542F3  sub         esp,0CCh  
006542F9  push        ebx  
006542FA  push        esi  
006542FB  push        edi  
006542FC  lea         edi,[ebp-0CCh]  
00654302  mov         ecx,33h  
00654307  mov         eax,0CCCCCCCCh  
0065430C  rep stos    dword ptr es:[edi]  
0065430E  mov         ecx,offset _D0BBC2EA_Source@cpp (065C003h)  
00654313  call        @__CheckForDebuggerJustMyCode@4 (065121Ch)  
00654318  mov         dword ptr [a],0Ah  
0065431F  mov         eax,dword ptr [a]  
00654322  shl         eax,1  
00654324  push        eax  
00654325  push        offset string "d\n" (0657BD8h)  
0065432A  call        _printf (0651046h)  
0065432F  add         esp,8  
00654332  mov         eax,dword ptr [a]  
00654335  shr         eax,1  
00654337  push        eax  
00654338  push        offset string "\x8f\x9c\x8eZ:%d\n" (0657BE8h)  
0065433D  call        _printf (0651046h)  
00654342  add         esp,8  
00654345  xor         eax,eax  
00654347  pop         edi  
00654348  pop         esi  
00654349  pop         ebx  
0065434A  add         esp,0CCh  
00654350  cmp         ebp,esp  
00654352  call        __RTC_CheckEsp (0651226h)  
00654357  mov         esp,ebp  
00654359  pop         ebp  
0065435A  ret

 

残念ながら期待していた違いは得られなかった。

おそらくVisual Studioではコンパイラが最適化しているんだろうか。

 

全然別のネタに発展してしまったが、私が理解したかったのは

左シフト:値 * (2^n)

右シフト:値 / (2^n)

ということ。

いやほんとに全然違うこと調べんじゃん。