32位汇编语言学习笔记(12)--分析switch语句的汇编代码



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 //如果result大于106,跳转到0xe + 0x15= 0x23,default分支
  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 //跳转到0x1c+0x1b=0x37
 1c:  b8 70 00 00 00         mov   $0x70,%eax //eax = 0x70=112 case 102分支
 21:  eb 0c                  jmp   2f //跳转到0x0c+0x23=0x2f
 23:  b8 00 00 00 00         mov   $0x0,%eax //result=0,default分支
 28:  eb 0d                  jmp   37 //跳转到0x0d+0x2a=0x37
 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 //跳转到0x03+0x34=0x37
 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各个分支语句的地址。

你可能感兴趣的:(Linux)