#include
void f(int a)
{
switch(a) {
case 1:
case 2:
case 7:
case 10:
printf("1, 2, 7, 10\n");
break;
case 3:
case 4:
case 5:
case 6:
printf("3, 4, 5, 6\n");
break;
case 8:
case 9:
case 20:
case 21:
printf("8, 9, 20, 21\n");
break;
case 22:
printf("22\n");
break;
default:
printf("default.\n");
break;
}
}
int main()
{
f(4);
}
#if 0
编译器会通过某种派发机制来降低代码的冗余度。
/*
* gcc
*/
在编译这种多对一的swith语句时,GCC会生成统一的转移表。
/*
* ARM64
*/
因为输入值为零的情况没有对应的处理方法,所以GCC会从输入值为1的特例开始枚举各个分支,以便把转移表压缩得尽可能小。
能把所有的偏移量信息编码为8位字节型数据,封装在单条指令的opcode里。
arm64程序的每条指令都对应着4个字节的opcode。
本例这种类型的小型代码中,各分支偏移量的具体数值不会很大。GCC能够充分利用这一现象,构造出单字节指针组成的转移表。
#endif
#if 0
/*
* intel
*/
0000000000001149 :
1149: f3 0f 1e fa endbr64
114d: 55 push %rbp
114e: 48 89 e5 mov %rsp,%rbp
1151: 48 83 ec 10 sub $0x10,%rsp
1155: 89 7d fc mov %edi,-0x4(%rbp)
1158: 83 7d fc 16 cmpl $0x16,-0x4(%rbp)
115c: 77 5c ja 11ba
115e: 8b 45 fc mov -0x4(%rbp),%eax
1161: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx
1168: 00
1169: 48 8d 05 c4 0e 00 00 lea 0xec4(%rip),%rax # 2034 <_IO_stdin_used+0x34>
1170: 8b 04 02 mov (%rdx,%rax,1),%eax
1173: 48 98 cltq
1175: 48 8d 15 b8 0e 00 00 lea 0xeb8(%rip),%rdx # 2034 <_IO_stdin_used+0x34>
117c: 48 01 d0 add %rdx,%rax
117f: 3e ff e0 notrack jmpq *%rax
1182: 48 8d 3d 7b 0e 00 00 lea 0xe7b(%rip),%rdi # 2004 <_IO_stdin_used+0x4>
1189: e8 c2 fe ff ff callq 1050
118e: eb 37 jmp 11c7
1190: 48 8d 3d 79 0e 00 00 lea 0xe79(%rip),%rdi # 2010 <_IO_stdin_used+0x10>
1197: e8 b4 fe ff ff callq 1050
119c: eb 29 jmp 11c7
119e: 48 8d 3d 76 0e 00 00 lea 0xe76(%rip),%rdi # 201b <_IO_stdin_used+0x1b>
11a5: e8 a6 fe ff ff callq 1050
11aa: eb 1b jmp 11c7
11ac: 48 8d 3d 75 0e 00 00 lea 0xe75(%rip),%rdi # 2028 <_IO_stdin_used+0x28>
11b3: e8 98 fe ff ff callq 1050
11b8: eb 0d jmp 11c7
11ba: 48 8d 3d 6a 0e 00 00 lea 0xe6a(%rip),%rdi # 202b <_IO_stdin_used+0x2b>
11c1: e8 8a fe ff ff callq 1050
11c6: 90 nop
11c7: 90 nop
11c8: c9 leaveq
11c9: c3 retq
00000000000011ca :
11ca: f3 0f 1e fa endbr64
11ce: 55 push %rbp
11cf: 48 89 e5 mov %rsp,%rbp
11d2: bf 04 00 00 00 mov $0x4,%edi
11d7: e8 6d ff ff ff callq 1149
11dc: b8 00 00 00 00 mov $0x0,%eax
11e1: 5d pop %rbp
11e2: c3 retq
11e3: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
11ea: 00 00 00
11ed: 0f 1f 00 nopl (%rax)
/*
* arm
*/
000000000040055c :
40055c: a9be7bfd stp x29, x30, [sp, #-32]!
400560: 910003fd mov x29, sp
400564: b9001fa0 str w0, [x29, #28]
400568: b9401fa0 ldr w0, [x29, #28]
40056c: 7100241f cmp w0, #0x9
400570: 5400014c b.gt 400598
400574: 7100201f cmp w0, #0x8
400578: 5400034a b.ge 4005e0 // b.tcont
40057c: 7100181f cmp w0, #0x6
400580: 5400020c b.gt 4005c0
400584: 71000c1f cmp w0, #0x3
400588: 5400024a b.ge 4005d0 // b.tcont
40058c: 7100041f cmp w0, #0x1
400590: 5400038b b.lt 400600 // b.tstop
400594: 1400000b b 4005c0
400598: 7100541f cmp w0, #0x15
40059c: 540000cc b.gt 4005b4
4005a0: 7100501f cmp w0, #0x14
4005a4: 540001ea b.ge 4005e0 // b.tcont
4005a8: 7100281f cmp w0, #0xa
4005ac: 540000a0 b.eq 4005c0 // b.none
4005b0: 14000014 b 400600
4005b4: 7100581f cmp w0, #0x16
4005b8: 540001c0 b.eq 4005f0 // b.none
4005bc: 14000011 b 400600
4005c0: 90000000 adrp x0, 400000 <_init-0x3e8>
4005c4: 911ba000 add x0, x0, #0x6e8
4005c8: 97ffffa2 bl 400450
4005cc: 14000011 b 400610
4005d0: 90000000 adrp x0, 400000 <_init-0x3e8>
4005d4: 911be000 add x0, x0, #0x6f8
4005d8: 97ffff9e bl 400450
4005dc: 1400000d b 400610
4005e0: 90000000 adrp x0, 400000 <_init-0x3e8>
4005e4: 911c2000 add x0, x0, #0x708
4005e8: 97ffff9a bl 400450
4005ec: 14000009 b 400610
4005f0: 90000000 adrp x0, 400000 <_init-0x3e8>
4005f4: 911c6000 add x0, x0, #0x718
4005f8: 97ffff96 bl 400450
4005fc: 14000005 b 400610
400600: 90000000 adrp x0, 400000 <_init-0x3e8>
400604: 911c8000 add x0, x0, #0x720
400608: 97ffff92 bl 400450
40060c: d503201f nop
400610: d503201f nop
400614: a8c27bfd ldp x29, x30, [sp], #32
400618: d65f03c0 ret
000000000040061c :
40061c: a9bf7bfd stp x29, x30, [sp, #-16]!
400620: 910003fd mov x29, sp
400624: 52800080 mov w0, #0x4 // #4
400628: 97ffffcd bl 40055c
40062c: 52800000 mov w0, #0x0 // #0
400630: a8c17bfd ldp x29, x30, [sp], #16
400634: d65f03c0 ret
#endif