Swithch反彙編(四種)
阿新 • • 發佈:2022-05-07
------------恢復內容開始------------
Switch語法格式
Switch(表示式)
{
case 常量表達式1:
語句;
break;
case 常量表達式2:
語句;
break;
case 常量表達式3:
語句;
break;
default:
語句;
break;
}
Switch注意事項
- case後面必須是常量表達式
- case後常量表達式的值不一樣
- switch後面表示式必須為整數型別其它型別諸如float double 等型別均不可以
- case如果沒有新增break語句則會繼續向下執行下面的case
- dafault語句可以沒有,如果所有case都不匹配會預設執行default語句
分支語句的增加之反彙編
分支語句少於等於3條與if—else語句的反彙編相同(case 值連續)
0040103E cmp dword ptr [ebp-4],1 00401042 je tast+32h (00401052) 00401044 cmp dword ptr [ebp-4],2 00401048 je tast+41h (00401061) 0040104A cmp dword ptr [ebp-4],3 0040104E je tast+50h (00401070) 00401050 jmp tast+5Fh (0040107f) 00401052 push offset string "1" (00422028) 00401057 call printf (00401130) 0040105C add esp,4 0040105F jmp tast+6Ch (0040108c) 00401061 push offset string "2" (00422024) 00401066 call printf (00401130) 0040106B add esp,4 0040106E jmp tast+6Ch (0040108c) 00401070 push offset string "4" (00422020) 00401075 call printf (00401130) 0040107A add esp,4 0040107D jmp tast+6Ch (0040108c) 0040107F push offset string "5" (0042201c)
分支語句大於三條生成一張大表(但是不一定,假如差值大的話就會生成if—else)(case後面的常量可以時無序的,並不影響大表的生成)編譯的時候就把地址排好了
#include "stdafx.h" void test(int x) { switch(x) { case 2: printf("2"); break; case 3: printf("3"); break; case 4: printf("4"); break; case 5: printf("5"); break; case 6: printf("6"); break; default: printf("5"); break; } } int main(int argc, char* argv[]) { test(5); return 0; }
case的值是從100-109彙編程式碼如下:
0040D7D8 mov eax,dword ptr [ebp+8]
0040D7DB mov dword ptr [ebp-4],eax
0040D7DE mov ecx,dword ptr [ebp-4]
0040D7E1 sub ecx,64h // 這個是第一個case
0040D7E4 mov dword ptr [ebp-4],ecx
0040D7E7 cmp dword ptr [ebp-4],9 //這是case的總個數 :9+1
0040D7EB ja $L550+0Fh (0040d897)
0040D7F1 mov edx,dword ptr [ebp-4]
0040D7F4 jmp dword ptr [edx*4+40D8B5h]//這就是生成的表
$L532:
0040D7FB push offset string "100" (00422fc0)
0040D800 call printf (00401130)
0040D805 add esp,4
0040D808 jmp $L550+1Ch (0040d8a4)
$L534:
0040D80D push offset string "101" (00422fbc)
0040D812 call printf (00401130)
0040D817 add esp,4
0040D81A jmp $L550+1Ch (0040d8a4)
$L536:
0040D81F push offset string "102" (00422fb8)
0040D824 call printf (00401130)
0040D829 add esp,4
0040D82C jmp $L550+1Ch (0040d8a4)
$L538:
0040D82E push offset string "103" (00422fb4)
0040D833 call printf (00401130)
0040D838 add esp,4
0040D83B jmp $L550+1Ch (0040d8a4)
$L540:
0040D83D push offset string "104" (00422fb0)
0040D842 call printf (00401130)
0040D847 add esp,4
0040D84A jmp $L550+1Ch (0040d8a4)
$L542:
0040D84C push offset string "105" (00422fac)
0040D851 call printf (00401130)
0040D856 add esp,4
0040D859 jmp $L550+1Ch (0040d8a4)
$L544:
0040D85B push offset string "106" (00422f5c)
0040D860 call printf (00401130)
0040D865 add esp,4
0040D868 jmp $L550+1Ch (0040d8a4)
$L546:
0040D86A push offset string "107" (00422028)
0040D86F call printf (00401130)
0040D874 add esp,4
0040D877 jmp $L550+1Ch (0040d8a4)
$L548:
0040D879 push offset string "108" (00422024)
0040D87E call printf (00401130)
0040D883 add esp,4
0040D886 jmp $L550+1Ch (0040d8a4)
$L550:
0040D888 push offset string "109" (00422020)
0040D88D call printf (00401130)
0040D892 add esp,4
0040D895 jmp $L550+1Ch (0040d8a4)
0040D897 push offset string "6" (0042201c)
0040D89C call printf (00401130)
說明ja 指令 jump above,大於時跳轉(無符號),也就是比較引數x-1和3(case中的最大差值),最大差值就是最大值減最小值
得出的結論會給生成一個大表來直接查詢
我們假如把case裡面的值刪除兩個項會發生什麼變化
#include<stdio.h>
#include "stdafx.h"
void test(int x)
{
switch(x)
{
case 100:
printf("100");
break;
case 103:
printf("103");
break;
case 104:
printf("104");
break;
case 105:
printf("105");
break;
case 106:
printf("106");
break;
case 107:
printf("107");
break;
case 108:
printf("108");
break;
case 109:
printf("109");
break;
default:
printf("5");
break;
}
}
int main(int argc, char* argv[])
{
test(106);
return 0;
}
總結刪除兩個時,編譯器仍然生成大表來儲存,沒有case的值 會儲存預設的地址
當刪除到6個時編譯器會幫我們建立小表
#include<stdio.h>
#include "stdafx.h"
void test(int x)
{
switch(x)
{
case 100:
printf("100");
break;
case 107:
printf("107");
break;
case 108:
printf("108");
break;
case 109:
printf("109");
break;
default:
printf("5");
break;
}
}
int main(int argc, char* argv[])
{
test(106);
return 0;
}
小表用來存放並不存在的case,然後通過大表來尋找到default
case後面常量表達式改成好不連續的值
#include<stdio.h>
#include "stdafx.h"
void test(int x)
{
switch(x)
{
case 1:
printf("100");
break;
case 5:
printf("107");
break;
case 200:
printf("108");
break;
case 9:
printf("109");
break;
case 300:
printf("109");
break;
default:
printf("5");
break;
}
}
int main(int argc, char* argv[])
{
test(103);
return 0;
}
------------恢復內容結束------------