50、52 などのケースがアセンブリ言語でどのように決定されたかを理解するのに少し苦労しています。
私が理解していることから、ジャンプ テーブルは各ケースで実行するアクションに対応し、edx > 5 のチェックはケースが 0 から 5 の範囲であることを意味しますか? 1 はデフォルトのケースなので省略されていると思いますが、5 が省略されているのはなぜですか?
ケース 55 があるべきだと思います: where result *= result, no?
誰かが説明を手伝ってくれるなら、それは素晴らしいことです。ありがとうございました!
int switch_prob(int x) { int result = x; switch (x) { case 50: case 52: result <<= 2; break; case 53: result >>= 2; break; case 54: result *= 3; break; default: result += 10; } return result; }
図 3.38 に、逆アセンブルされたプロシージャのオブジェクト コードを示します。4 行目から 16 行目に示されているコードの部分のみに注目します。4 行目で、パラメーター x (%ebp に対するオフセット 8) がプログラム変数 result に対応するレジスター %eax にロードされていることがわかります。11 行目の「lea 0x0(%esi), %esi」命令は、12 行目の命令を 16 の倍数のアドレスから開始させるために挿入された nop 命令です。
ジャンプ テーブルは、メモリの別の領域にあります。デバッガー GDB を使用して、コマンド x/6w 0x8048468 を使用して、アドレス 0x8048468 で始まるメモリの 6 つの 4 バイト ワードを調べることができます。GDB は以下を出力します。
(gdb) x/6w 0x8048468: 0x080483d5 0x080483eb 0x080483d5 0x0x80483e0 0x8048478: 0x080483e5 0x080483e8 (gdb)
アセンブリ コード:
1: 080483c0 <switch_prob>: 2: 80483c0: push %ebp 3: 80483c1: mov %esp,%ebp 4: 80483c3: mov 0x8(%ebp),%eax // X is copied into eax ; eax = x 5: 80483c6: lea 0xffffffce(%eax),%edx // placeholder 6: 80483c9: cmp $0x5, %edx // Compare edx (3rd argument) with 5; Edx - 5 // clearly, edx is x 7: 80483cc: ja 80483eb <switch_prob+0x2b> // if edx - 5 > 0, Jump into line 16 (default) 8: 80483ce: jmp *0x8048468(,%edx,4) // Go into the jump table 9: 80483d5: shl $0x2, %eax // eax << 2 10: 80483d8: jmp 80483ee <switch_prob+0x2e> // Jump to line 17 11: 80483da: lea 0x0(%esi),%esi // esi = esi NOP. Filling in N bytes 12: 80483e0: sar $0x2, %eax // eax >> 2 13: 80483e3: jmp 80483ee <switch_prob+0x2e> // Jump to line 17 14: 80483e5: lea (%eax, %eax, 2), %eax // eax = eax + 2(eax) 15: 80483e8: imul %eax, %eax // eax *= eax 16: 80483eb: add $0xa, %eax // eax += 10 17: 80483ee: mov %ebp, %esp // esp = ebp 18: 80483f0: pop %ebp 19: 80483f1: ret