[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가 많고 연속적인 경우 스위치문이 속도면에서 유리해보인다.