2

GCC で最適化して switch ステートメントをコンパイルすると、次のようなジャンプ テーブルが設定されます。

(fcn) sym.foo 148
  sym.foo (unsigned int arg1);
; arg unsigned int arg1 @ rdi
0x000006e0      83ff06         cmp edi, 6                              ; arg1
0x000006e3      0f87a7000000   ja case.default.0x790
0x000006e9      488d156c0100.  lea rdx, [0x0000085c]
0x000006f0      89ff           mov edi, edi
0x000006f2      4883ec08       sub rsp, 8
0x000006f6      486304ba       movsxd rax, dword [rdx + rdi*4]
0x000006fa      4801d0         add rax, rdx                            ; '('
;-- switch.0x000006fd:
0x000006fd      ffe0           jmp rax                                 ; switch table (7 cases) at 0x85c

それを行うための最良の方法はMOVSXDADD

movsxd rax, dword [rdx + rdi*4]
add rax, rdx

LEAで使うのと同じじゃない?displacement

lea rax, [rdx + rdi*4 + rdx]

ここで何が起こっているのか、おそらく私には理解できないと思います。RDXジャンプ台のスタートのようです。RDIswitch ステートメントへの入力引数です。しかし、なぜ 2 回追加するのRDXでしょうか。

これは、私がコンパイルしていたswitch文です-O3

int foo (int x) {
  switch(x) {
    //case 0: puts("\nzero"); break;
    case 1: puts("\none"); break;
    case 2: puts("\ntwo"); break;
    case 3: puts("\nthree"); break;
    case 4: puts("\nfour"); break;
    case 5: puts("\nfive"); break;
    case 6: puts("\nsix"); break;
  }
  return 0;
}
4

2 に答える 2