[Assembly/C] switch, 점프테이블
스위치문 : case가 연속적일때
#include <iostream>
int main() {
int x = 1;
switch (x) {
case 1:
printf("1\n");
case 2:
printf("2\n");
case 3:
printf("3\n");
case 4:
printf("4\n");
case 5:
printf("5\n");
case 6:
printf("6\n");
}
}
int x = 1;
001C1096 mov dword ptr [ebp-8],1
switch (x) {
001C109D mov eax,dword ptr [ebp-8]
001C10A0 mov dword ptr [ebp-4],eax
001C10A3 mov ecx,dword ptr [ebp-4]
001C10A6 sub ecx,1
001C10A9 mov dword ptr [ebp-4],ecx
001C10AC cmp dword ptr [ebp-4],5
001C10B0 ja 001C110A // 1: 조건시 스위치문 탈출
001C10B2 mov edx,dword ptr [ebp-4]
001C10B5 jmp dword ptr [edx*4+001C1110h] // 2:
case 1:
printf("1\n");
001C10BC push 1C2100h
001C10C1 call 001C1040
001C10C6 add esp,4
case 2:
printf("2\n");
001C10C9 push 1C2104h
001C10CE call 001C1040
001C10D3 add esp,4
...
1
x값이 case 가장 큰 값인 6보다 클경우 스위치문을 탈출한다. 여기서 x를 비교할때 (ebp-4)를 -1하고 case 6대신 -1한 5와 비교하는 이유는 점프테이블을 생성하기 위해 가장 작은 값을 0으로 맞추기 위해서이다.
(case가 연속적인데 0부터 시작하면 x값 그대로 비교되는걸 확인했다.)
점프 테이블
2
001C1110h 점프테이블을 살펴보면
0x001C1110 bc 10 1c 00 ?...
0x001C1114 c9 10 1c 00 ?...
0x001C1118 d6 10 1c 00 ?...
0x001C111C e3 10 1c 00 ?...
0x001C1120 f0 10 1c 00 ?...
0x001C1124 fd 10 1c 00 ?...
4바이트 단위로 배열처럼 코드 주소가 저장되어있다. -> 점프테이블 즉 if else처럼 하나하나 비교 후 점프하는 것이 아닌 점프테이블을 생성하고 그에 따라 점프하는것
001C10B5 jmp dword ptr [edx*4+001C1110h]
edx*4 -> x가 1이라면 edx는 0이니 첫번째 테이블.. x가 3이라면 edx는 2이며 4바이트씩 두번 더한 세번째 테이블의 코드주소로 점프하는 식이다.
스위치문: case가 적을때
#include <iostream>
int main() {
int x = 1;
switch (x) {
case 1:
printf("1\n");
case 2:
printf("2\n");
case 3:
printf("3\n");
}
}
switch (x) {
0089109D mov eax,dword ptr [ebp-8]
008910A0 mov dword ptr [ebp-4],eax
008910A3 cmp dword ptr [ebp-4],1
008910A7 je 008910B7
008910A9 cmp dword ptr [ebp-4],2
008910AD je 008910C4
008910AF cmp dword ptr [ebp-4],3
008910B3 je 008910D1
008910B5 jmp 008910DE
case 1:
printf("1\n");
008910B7 push 892100h
ㄴ if else 문처럼 하나하나 비교하고 점프하기때문에 내부적으로 if else와 차이가 없다.
결론 및 느낀점
case가 적을떈 if else와 동작이 같지만, case가 많고 연속적인 경우 스위치문이 속도면에서 유리해보인다.