I am analysing how switch is converted from C to aseembly (GAS). I don't understand the GAS's trick how the 'lower edge' default is triggered.
There is a conditional jump for 'higher edge' :
cmpl $8, %eaxja .L2
There is no conditional jump for 'lower edge', just a jump into jump table
So, how is the 'lower' default handled?e.g. when i input 10 - DEFAULT is displayed
-----------part of code where I think the trick is hidden(switch's range is 11-19, uneven numbers)
call scanf #switch argument is in %eax movl -4(%rbp), %eax subl $11, %eax cmpl $8, %eax ja .L2 # higher edge default movl %eax, %eax leaq 0(,%rax,4), %rdx leaq .L4(%rip), %rax movl (%rdx,%rax), %eax movslq %eax, %rdx leaq .L4(%rip), %rax addq %rdx, %rax jmp *%rax
-----------below is source code
C code :
#include <stdio.h>int main(){ int a; printf("Insert a number : "); scanf("%d",&a); switch(a) { case 11: printf("ELEVEN\n"); break; case 13: printf("THIRTEEN\n"); break; case 15: printf("FIFTEEN\n"); break; case 17: printf("SEVENTEEN\n"); break; case 19: printf("NINETEEN\n"); break; default: printf("DEFAULT\n"); break; } return 0;}
GAS code:
.file "switch1.c" .text .def __main; .scl 2; .type 32; .endef .section .rdata,"dr".LC0: .ascii "Insert a number : \0".LC1: .ascii "%d\0".LC2: .ascii "ELEVEN\0".LC3: .ascii "THIRTEEN\0".LC4: .ascii "FIFTEEN\0".LC5: .ascii "SEVENTEEN\0".LC6: .ascii "NINETEEN\0".LC7: .ascii "DEFAULT\0" .text .globl main .def main; .scl 2; .type 32; .endef .seh_proc mainmain: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $48, %rsp .seh_stackalloc 48 .seh_endprologue call __main leaq .LC0(%rip), %rcx call printf leaq -4(%rbp), %rax movq %rax, %rdx leaq .LC1(%rip), %rcx call scanf movl -4(%rbp), %eax subl $11, %eax cmpl $8, %eax ja .L2 movl %eax, %eax leaq 0(,%rax,4), %rdx leaq .L4(%rip), %rax movl (%rdx,%rax), %eax movslq %eax, %rdx leaq .L4(%rip), %rax addq %rdx, %rax jmp *%rax .section .rdata,"dr" .align 4.L4: .long .L3-.L4 .long .L2-.L4 .long .L5-.L4 .long .L2-.L4 .long .L6-.L4 .long .L2-.L4 .long .L7-.L4 .long .L2-.L4 .long .L8-.L4 .text.L3: leaq .LC2(%rip), %rcx call puts jmp .L9.L5: leaq .LC3(%rip), %rcx call puts jmp .L9.L6: leaq .LC4(%rip), %rcx call puts jmp .L9.L7: leaq .LC5(%rip), %rcx call puts jmp .L9.L8: leaq .LC6(%rip), %rcx call puts jmp .L9.L2: leaq .LC7(%rip), %rcx call puts nop.L9: movl $0, %eax addq $48, %rsp popq %rbp ret .seh_endproc .ident "GCC: (GNU) 7.4.0" .def printf; .scl 2; .type 32; .endef .def scanf; .scl 2; .type 32; .endef .def puts; .scl 2; .type 32; .endef