C語言switch語句的組合語言實現
C語言switch語句的組合語言實現
一個好的編譯器一定是一群頂尖軟體高手們集體長時間創作的作品了,所以研究研究編譯器的編譯過程就是在向這些高手們學習。說到底,編譯器也是一個很好的老師了,它可以為我們揭開高階語言實現的奧祕,為那些永不滿足於表面現象的程式設計師深入掌握一門語言提供一個很好的途徑。來看看微軟的cl 8.0編譯器是怎樣來編譯C語言的switch語句的,照例寫一個測試的例子:
int test()
{
int i,j;
i=j=0;
switch(i)
{
case 1:j+=1;break;
case 2:j+=2;break
default:j+=5;
}
return 0;
}
看看生成的彙編程式碼:
; 5:
; 6: switch(i)
movecx, DWORD PTR _i$[ebp]
movDWORD PTR tv64[ebp], ecx
;case 1:
cmpDWORD PTR tv64[ebp], 1
jeSHORT [email protected]
;case 2:
cmpDWORD PTR tv64[ebp], 2
jeSHORT [email protected]
;default:
jmpSHORT [email protected]
; 7: {
; 8: case 1:j+=1;break;
movedx, DWORD PTR _j$[ebp]
addedx, 1
movDWORD PTR _j$[ebp], edx
jmpSHORT [email protected]
; 9: case 2:j+=2;break;
moveax, DWORD PTR _j$[ebp]
addeax,
movDWORD PTR _j$[ebp], eax
jmpSHORT [email protected]
; 10: default:j+=5;
movecx, DWORD PTR _j$[ebp]
addecx, 5
movDWORD PTR _j$[ebp], ecx
; 11: }
; 12:
; 13: return 0;
xoreax, eax
; 14: }
這段彙編程式碼是很好理解的,就是比較並跳轉的過程。
下面看看一個比較複雜的switch
int test()
{
int i,j;
i=j=0;
switch(i)
{
case 1:j+=1;break;
case 2:j+=2;break;
case 3:j+=3;break;
case 4:j+=4;break;
default:j+=10;
}
return 0;
}
再來看看編譯器生成的彙編程式碼:
; 5:
; 6: switch(i)
movecx, DWORD PTR _i$[ebp]
movDWORD PTR tv64[ebp], ecx
movedx, DWORD PTR tv64[ebp]
subedx, 1
movDWORD PTR tv64[ebp], edx
cmpDWORD PTR tv64[ebp], 3
jaSHORT [email protected]
moveax, DWORD PTR tv64[ebp]
jmpDWORD PTR [email protected][eax*4]
;以上的彙編程式碼相當於以下的偽指令:
if(i-1 > 3)
{
goto [email protected];//跳轉到default
}
else
{
goto [email protected][i-1];//case 1,case 2,case 3,case 4的情況
}
[email protected]是一個跳轉表,通過它就可以跳轉到相應的處理程式碼中去,看來微軟的編譯器還是很聰明的,會在編譯時對case的值作一些判斷,這也就是所謂的優化吧。
; 7: {
; 8: case 1:j+=1;break;
movecx, DWORD PTR _j$[ebp]
addecx, 1
movDWORD PTR _j$[ebp], ecx
jmpSHORT [email protected]
; 9: case 2:j+=2;break;
movedx, DWORD PTR _j$[ebp]
addedx, 2
movDWORD PTR _j$[ebp], edx
jmpSHORT [email protected]
; 10: case 3:j+=3;break;
moveax, DWORD PTR _j$[ebp]
addeax, 3
movDWORD PTR _j$[ebp], eax
jmpSHORT [email protected]
; 11: case 4:j+=4;break;
movecx, DWORD PTR _j$[ebp]
addecx, 4
movDWORD PTR _j$[ebp], ecx
jmpSHORT [email protected]
; 12: default:j+=10;
movedx, DWORD PTR _j$[ebp]
addedx, 10; 0000000aH
movDWORD PTR _j$[ebp], edx
; 13: }
......
[email protected];case 1
[email protected];case 2
[email protected];case 3
[email protected];case 4
下面來看看加大各case的差別會帶來怎樣的差異:
int test()
{
int i,j;
i=j=0;
switch(i)
{
case 1:j+=1;break;
case 2:j