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, %eax
ja .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 main
main:
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