程序集x86-64:switch语句中的默认值

时间:2017-02-20 19:09:28

标签: assembly switch-statement x86-64

我正在尝试模仿以下代码,它应该在汇编中打印1 2:

    a=1
    switch(a) {
            default: print 1;
            case 2: print 2;
    }

这就是我所拥有的:

    movq $1, a
    pushq a
    popq %rdx
    cmp $1, %rdx
    jne if_0
    jmp if_1
if_0:
    movq $1, %rsi
    pushq %rsi
    movq $format, %rdi
    popq %rsi
    pushq %rbp
    call printf
    movq %rbp, %rsp
    popq %rbp
    jmp if_2
if_1:
    movq $2, %rsi
    pushq %rsi
    popq %r11
    cmpq %rdx, %r11
    je if_2
    jne if_3
if_2:
    movq $2, %rsi
    pushq %rsi
    movq $format, %rdi
    popq %rsi
    pushq %rbp
    call printf
    movq %rbp, %rsp
    popq %rbp
    jmp if_4
if_3:
if_4:
    jmp switch_0

在顶部,我只是将变量与1进行比较,因为我不确定该怎么做。在进行默认情况之前,我如何向前看并看到a不等于2?

2 个答案:

答案 0 :(得分:2)

您正在充当编译器,因此您可以在所有情况下“向前看”,如果交换机 default,则会看到2案例

或者,如果你是一个更精简的“编译器”,你可以看到代码始终打印1 2而不进行任何比较。

答案 1 :(得分:2)

您的代码似乎过于复杂。

查看C代码和相应的ASM代码

int printer(int a) 
{
    switch(a) 
    {
            default: printf("%s","1");
            case 2: printf("%s","2");
    }
}

是的 - 我知道你设置了= 1 - 但是如果你事先知道结果,那么比较没有任何意义。在非优化的ASM结果下面 - 有putchar因为字符串是一个字母 - 但是这可以根据需要更改为printf。

printer(int):
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], edi
        mov     eax, DWORD PTR [rbp-4]
        cmp     eax, 2
        je      .L5
        mov     edi, 49
        call    putchar
.L5:
        mov     edi, 50
        call    putchar
        nop
        leave
        ret

通过优化,它甚至更简单

printer(int):
        cmp     edi, 2
        jne     .L13
        mov     edi, 50
        jmp     putchar
.L13:
        sub     rsp, 8
        mov     edi, 49
        call    putchar
        mov     edi, 50
        add     rsp, 8
        jmp     putchar

你可能已经注意到了gcc技巧 - 它完全删除了堆栈帧和ret指令。