title: switch语句的汇编实现 date: 2014-11-26 15:40:06 categories: 编译器

tags: 汇编

C语言中switch语句的汇编实现。

一般来说,C语言中switch语句相当于一堆的if-else语句的累积,除非case很多的时候, 如果case之间的跨度不是很大,此时编译器一般会作优化,不再使用if-else集合,而是 使用一个跳转表,这样可以避免大量的compare计算。

少量case时的switch语句

代码示例如下,

```c switch.c

include

void translate(int n) { char *p; switch(n) { case 1: p = "one"; break; case 2: p = "two"; break; case 3: p = "three"; break; } }


编译成汇编代码,

```bash
gcc -S switch.c

汇编代码如下,

# ignore some text ...
.LC0:
    .string "one"
.LC1:
    .string "two"
.LC2:
    .string "three"
.text
.global translate
    .type translate, @function
translate:
    # ignore some text
    # %eax keep the value of 'n'
    cmpl    $2, %eax
    je  .L4
    cmpl    $3, %eax
    je  .L5
    cmpl    $1, %eax
    jne .L1
.L3:
    movq $.LC0, -16(%rbp)   # -16(%rbp) is variable p
    jmp .L1
.L4:
    movq $.LC1, -16(%rbp)   # -16(%rbp) is variable p
    jmp .L1
.L5:
    movq $.LC2, -16(%rbp)   # -16(%rbp) is variable p
    nop
.L1:
    leave
    ret
# ignore some text...

这完全就是一堆的if-else集合。

大量case时的switch语句

假如我们把上面的switch中的case数增加到8个,从case 10:一直到case 17, 则汇编代码变为,

# ignore some text
# %eax keep the value of 'n'
    subl    $10, %eax
    cmpl    $7, %eax
    ja  .L1 # 如果%eax > 7则跳转,
            # ja是无符号比较,所以即使n < 10,也就是说这里的%eax < 0,也会跳转
     # 根据跳转表进行跳转
     movq   .L11(,%eax,8), %rax
     jmp    *%rax
     .section   .rodata
     .align 8
     .align 4
.L11:
    .quad   .L3
    .quad   .L4
    .quad   .L5
    .quad   .L6
    .quad   .L7
    .quad   .L8
    .quad   .L9
    .quad   .L10
.L3: # 具体的case内容
    # xxx
.L4: # 具体的case内容
    # xxx
# ignore some text