Switch statement

  jump table is an array where entry i is the address of a code segment implementing the action the program should take when the switch index(开关索引值) equals i.

  jump table是一个数组,这个数组其中一个条目,比如条目i是一个代码段的地址,这个代码段的代码实现了当switch index等于i时程序应该采取的动作。

  The code performs an array reference(数组引用)into the jump table using the switch index to determine the target for a jump instruction.

程序代码用switch index来执行一个jump table内的数组引用,确定跳转指令的目标。(e.g.jmp *.L4(,%rdi,8))这句话理解起来相当别扭,记得看下面的习题就会豁然开朗。Practice Problem 3.30

  The advantage of using a jump table over a long sequence of if-elsestatements is that the time taken to perform the switch is independent of the number of switch cases.GCC selects the method of translating a switchstatement based on the number of cases and the sparsity of the case values.Jump tables are used when there are a number of cases(e.g. four or more)and they span a small range of values.

  和使用一组很长的if-else语句相比,使用jump table的优势是:程序执行switch语句所需要的时间与case val:的数量是相互独立的。GCC根据case val:的数量跟val的稀疏程度来翻译switch语句,当case val:数量很多(例如4个以上),而且val值的跨度范围比较小时,就会使用jump table


Practice Problem 3.31
For a C function switcher with the general structure

void switcher(long a, long b, long c, long *dest)
{
    long val;
    switch (a){
    case ____:    /*Case A*/
      c = ____;
      /*fall through*/
    case ____:    /*Case B*/
        val = ___;
        break;
    case ____:    /*Case C*/
    case ____:    /*Case D*/
        val = ___;
        break;
    case ____:    /*Case E*/
        val = ___;
        break;
    default:
        val = ___;
   }
   * dest = val;
}

GCC generates the assembly code and jump table shown in Figure 3.24.
  Fill in the missing parts of the C code. Except for the ordering of case labels C and D, there is only one way to fit the different cases into the template.

void switcher(long a, long b, long c, long *dest)
 a in %rdi, b in %rsi, c in %rdx, dest in %rcx
switcher:
  cmpq %7, %rdi
  ja   .L2
  jmp  *.L4(, %rdi, 8)
  .section    .rodata
.L7:
  xorq  $15, %rsi
  movq  %rsi, %rdx
.L3:
  leaq  112(%rdx), %rdi
  jmp   .L6
.L5:
  leaq (%rdx, %rsi), %rdi
  salq  $2, %rdi
  jmp  .L6
.L2:
  movq  %rsi, %rdi
.L6:
  movq %rdi, (%rcx)
  ret

jump table is:

.L4:
    .quad .L3
    .quad .L2
    .quad .L5
    .quad .L2
    .quad .L6
    .quad .L7
    .quad .L2
    .quad .L5
Answer:
void switcher(long a, long b, long c, long *dest)
 a in %rdi, b in %rsi, c in %rdx, d in %rcx
switcher:
  cmpq %7, %rdi    // a in %rdi => a-7
  ja   .L2         //a - 7 > 0 jump to the label .L2
  jmp  *.L4(, %rdi, 8)//array reference jump table
  .section    .rodata
.L7:                 //case 5:
  xorq  $15, %rsi    // b = 0000 0000 0000 0000 0000 0000 0000 1111 ^ b
  movq  %rsi, %rdx   // c = b
.L3:                 //case 0:
  leaq  112(%rdx), %rdi  // a = 112 + c
  jmp   .L6              //break;
.L5:                  //case 2:
  leaq (%rdx, %rsi), %rdi  // a = c + b
  salq  $2, %rdi           // a = 4 * a
  jmp  .L6                 //break
.L2:                   //default:
  movq  %rsi, %rdi         // a = b
.L6:
  movq %rdi, (%rcx)      // *dest = a
  ret

so the C code is :

void switcher(long a, long b, long c, long *dest)
{
    long val;
    switch (a){
    case 5:    /*Case A*/
      c = 15 ^ b;
      /*fall through*/
    case 0:    /*Case B*/
        val = 112 + c;
        break;
    case 2:    /*Case C*/
    case 7:    /*Case D*/
        val = 4 * (c + b);
        break;
    case 4 :    /*Case E*/
        val = a;
        break;
    default:
        val =  b;
   }
   * dest = val;
}

本题中,变量val没有被分配寄存器,val在逻辑上也是使用%rdi

你可能感兴趣的:(Switch statement)