조건이 많은 switch 문
source
#include <stdio.h>
void f (int a)
{
switch (a)
{
case 0: printf("zero\n"); break;
case 1: printf("one\n"); break;
case 2: printf("two\n"); break;
case 3: printf("three\n"); break;
case 4: printf("four\n"); break;
default: printf("something unknown\n"); break;
}
}
int main()
{
f(2);
}
x86 MSVC
$SG5332 DB 'zero', 0aH, 00H
$SG5334 DB 'one', 0aH, 00H
$SG5336 DB 'two', 0aH, 00H
$SG5338 DB 'three', 0aH, 00H
$SG5340 DB 'four', 0aH, 00H
$SG5342 DB 'something unknown', 0aH, 00H
EXTRN ___acrt_iob_func:PROC
EXTRN ___stdio_common_vfprintf:PROC
_main PROC
push OFFSET $SG5336
call _printf
add esp, 4
xor eax, eax
ret 0
_main ENDP
_a$ = 8 ; size = 4
f PROC
mov eax, DWORD PTR _a$[esp-4]
cmp eax, 4
ja SHORT $LN9@f
jmp DWORD PTR $LN13@f[eax*4]
$LN4@f:
mov DWORD PTR _a$[esp-4], OFFSET $SG5332
jmp _printf
$LN5@f:
mov DWORD PTR _a$[esp-4], OFFSET $SG5334
jmp _printf
$LN6@f:
mov DWORD PTR _a$[esp-4], OFFSET $SG5336
jmp _printf
$LN7@f:
mov DWORD PTR _a$[esp-4], OFFSET $SG5338
jmp _printf
$LN8@f:
mov DWORD PTR _a$[esp-4], OFFSET $SG5340
jmp _printf
$LN9@f:
mov DWORD PTR _a$[esp-4], OFFSET $SG5342
jmp _printf
npad 2
$LN13@f:
DD $LN4@f
DD $LN5@f
DD $LN6@f
DD $LN7@f
DD $LN8@f
f ENDP
함수 도입부를 보면 a
가 4보다 큰 경우 제어 흐름을 라벨 LN9@f
으로 넘긴다. 이 라벨에서는 something unknwon\n
을 인자로 하는 printf()
를 호출한다. a
가 4보다 작거나 같으면 4를 곱한 후, $LN13@f
테이블 주소에 더한다. 이게 바로 테이블 내에서 a
값에 따라 필요한 항목의 주소를 계산하는 과정이다. 이런 테이블을 분기 테이블 또는 점프 테이블이라고 한다. npad
는 다음 라벨을 정렬하는 어셈블리어 매크로로, 라벨이 4 바이트(또는 16바이트) 경계로 배열된 주소에 저장되게 해준다.