Switch in machine-level

김민욱·2025년 4월 23일

Switch statement

예제 코드

// switch example in C
long switch_eg(long x, long y, long z)
{
	long w = 1;
    switch(x) {
    case 1:
    	w = y*z;
        break;
    case 2:
    	w = y/z;
    case 3:
    	w += z;
        break;
    case 5:
    case 6:
    	w -= z;
        break;
    default :
    	w = 2;
    }
    return w;
}

Jump Table
switch statement의 각 case에 대한 주소를 저장하는 배열.
코드는 점프테이블의 주소로 간접 점프하여 타겟 코드블록으로 이동한다.
(switch -> jump table -> code block)

// jumptable example in assembly
.section	.rodata
	.align 8
.L4 :
	.quad	.L8 // x = 0
    .quad	.L3 // x = 1
    .quad	.L5 // x = 2
    .quad	.L9 // x = 3
    .quad	.L8 // x = 4, 위 코드에서는 missing case
    .quad	.L7 // x = 5
    .quad	.L7 // x = 6

각 타겟은 8bytes이고 .L4에 base address를 두고있다.
x=0과 x=4 모두 default 주소로 점프한다.
이처럼 switch jump table은 missing case도 모두 고려하여 작성되기 때문에 switch문에 조건으로 들어갈 항목은 되도록이면 순차적인 값이 효율적이다.

  • 직접 점프
jmp .L8

.L8 label로 표시된 타겟 주소로 점프한다.

  • 간접 점프
jmp *.L4(, %rdi, 8)

base adress 기준 8*x(주소는 8bytes이기 때문) 만큼 더해진 주소로 점프한다.

Fall-through case

	...
	long w = 1;
    switch (x) {
	...
	case 2:
    	w = y/z;
    case 3:
    	w += z;
        break;
    ...
    }
}

case 2를 보면 수행 후 break를 통해 switch문을 탈출하지 않고 case 3으로 넘어간다.
switch문 전에 초기화 된 w값은 1이지만, case 2를 거쳐 수행된 case 3의 w 값은 1이 아니다.
그러나 case 3 단독 점프라면 w의 값은 1이어야 한다.
이런 혼란을 막기 위해 내부적으로 fall-through는 다음과 같이 동작한다.

// fall-through handling in C
	case 2:
    	w = y/z;
        goto merge;

	case 3:
    	w = 1;
    merge :
    	w += z;
// fall-through handling in Assembly
.L5:					// Case 2
	movq %rsi, %rax		// 나눠지는 수 %rax로 복사
    cqto				
    // %rax에 있는 64비트 signed int를 128비트 signed bit로 확장
    // 확장된 값이 RDX에 저장됨
    idivq %rcx			// y/z, 나눗셈 결과는 %rax에 저장
    jmp .L6				// goto merge
.L9:					// Case 3
	movl $1, %eax		// w = 1
.L6:					// merge:
	addq %rcx, %rax		// w += z
    ret

Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
안성용, "시스템소프트웨어", 부산대학교

0개의 댓글