我正在分析如何将开关从C转换为组合(GAS)。我不了解GAS的窍门是如何触发“下边缘”默认设置的。
“更高边缘”存在条件跳转:
cmpl $8, %eax
ja .L2
“下边缘”没有条件跳转,只是跳转到跳转表中
那么,如何处理“较低”的默认设置? 例如当我输入10-显示DEFAULT
-------------我认为隐藏了窍门的部分代码 (交换机的范围是11-19,数字不均匀)
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
C代码:
#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代码:
.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