switch语句可以根据整数索引值进行多重分支选择,代码的可读性好,switch语句的汇编实现是通过跳转表来完成的,这样执行效率也很高。
int switch_eg(int x)
{
int result = x;
switch (x) {
case 100:
result*= 13;
break;
case 102:
result+= 10;
/*Fall through */
case 103:
result+= 11;
break;
case 104:
case 106:
result*= result;
break;
default:
result= 0;
}
return result;
}
gcc -c -O1 -m32 switch.c
objdump -d switch.o
switch.o: file format elf32-i386
Disassembly of section .text:
00000000
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 8b 45 08 mov 0x8(%ebp),%eax //eax = x = result
6: 8d 50 9c lea 0xffffff9c(%eax),%edx //edx = eax –0x64=eax-100
9: 83 fa 06 cmp $0x6,%edx //比较edx和6
c: 77 15 ja 23
e: ff 24 95 00 00 00 00 jmp *0x0(,%edx,4) //跳转到.rodata的首地址处加4*edx偏移的地址处
//获取的地址就是要跳转的地址。edx大于等于0,小于等于6 。
15: b8 14 05 00 00 mov $0x514,%eax //result = 0x514 =1300, case 100分支
1a: eb 1b jmp 37
1c: b8 70 00 00 00 mov $0x70,%eax //eax = 0x70=112 case 102分支
21: eb 0c jmp 2f
23: b8 00 00 00 00 mov $0x0,%eax //result=0,default分支
28: eb 0d jmp 37
2a: b8 67 00 00 00 mov $0x67,%eax //result = 0x67=103 case 103分支
2f: 83 c0 0b add $0xb,%eax //result += 11
32: eb 03 jmp 37
34: 0f af c0 imul %eax,%eax //result *= result case 104,106分支
37: 5d pop %ebp
38: c3 ret
jmp *0x0(,%edx,4),0x0会在链接时填充为.rodata(只读数据段)的起始地址。
objdump -s switch.o
switch.o: file format elf32-i386
Contents of section .text:
00005589e58b 45088d50 9c83fa06 7715ff24 U...E..P....w..$
001095000000 00b81405 0000eb1b b8700000 .............p..ta
002000eb0cb8 00000000 eb0db867 00000083 ...........g....
0030c00beb03 0fafc05d c3 .......].
Contents of section .rodata:
000015000000 23000000 1c0000002a000000 ....#.......*...
001034000000 23000000 34000000 4...#...4...
Contents of section .comment:
000000474343 3a202847 4e552920 342e312e .GCC: (GNU) 4.1.
001032203230 30383037 30342028 52656420 220080704 (Red
002048617420 342e312e 322d3434 2900 Hat4.1.2-44).
通过查看只读数据段的内容,可以确定里面存储的就是switch各个分支语句的地址。