2

C/C++ では、switch ステートメントはコンパイラによってジャンプ テーブルに下げられます。ARM と x86 のジャンプ テーブルの配置の違いに気付きました。

x86

x86 (および x86_64) の場合、ジャンプ テーブルは関数のに配置されることがよくあります (例: .rodata)。

  4005e0:       48 8b 45 d8             mov    -0x28(%rbp),%rax
  4005e4:       48 8b 0c c5 b0 0c 40    mov    0x400cb0(,%rax,8),%rcx
  4005eb:       00 
  4005ec:       ff e1                   jmpq   *%rcx
  4005ee:       8b 45 e8                mov    -0x18(%rbp),%eax
  4005f1:       83 e8 66                sub    $0x66,%eax

ARM の場合、ジャンプ テーブルは関数のコードとインターリーブされます。

 15c:   e28f2004        add     r2, pc, #4
 160:   e7911002        ldr     r1, [r1, r2]
 164:   e1a0f001        mov     pc, r1
 168:   000001a4        .word   0x000001a4
 16c:   000001b4        .word   0x000001b4
 170:   000001e4        .word   0x000001e4
 174:   00000214        .word   0x00000214
 178:   00000214        .word   0x00000214
 17c:   00000214        .word   0x00000214
 180:   00000214        .word   0x00000214
 184:   00000214        .word   0x00000214
 188:   000001c4        .word   0x000001c4
 18c:   000001f4        .word   0x000001f4

上記のコードは で生成されましclang 3.5 -target arm-none-eabi -march=armv7たが、同様のコードが で生成されgccます。

MIPS

完全を期すために、MIPS の switch ステートメントのコードを次に示します。ジャンプ台は.rodataセクションに配置されます。

 4002b8:    2c85000b    sltiu   a1,a0,11       
 4002bc:    afc40018    sw  a0,24(s8)       //local var that we switch on 
 4002c0:    10a00021    beqz    a1,400348 <main0+0xb4> // default case
 4002c4:    00000000    nop
 4002c8:    8fc10018    lw  at,24(s8)      //the var that we switch on is in at
 4002cc:    00011080    sll v0,at,0x2      // v0 = at<<2
 4002d0:    3c030040    lui v1,0x40        // v1 = 0x40<<16
 4002d4:    00431021    addu    v0,v0,v1   // v0 = (at<<2) + v1 
 4002d8:    8c421848    lw  v0,6216(v0)    // v0 = *((at<<2)+0x401848)
 4002dc:    00400008    jr  v0             // jump
 4002e0:    00000000    nop

jumptable ( 0x00401848) のアドレスは にあり.rodataます。

 $ readelf -e /tmp/muti-sw.mips.o  | grep .rodata
 [ 7] .rodata           PROGBITS        00401848 001848 00069a 00   A  0   0  4

上記のコードは、clang 3.9 で生成されました。

質問

ARM アーキテクチャではジャンプ テーブルが関数のコードとインターリーブされることが多く、x86 ではインターリーブされないのはなぜですか?

この答えは、キャッシュがARMで動作する方法がそれと関係があることを意味します。他の理由はありますか?

4

1 に答える 1