GCC が mov %eax,%eax を生成したのはなぜですか? また、これは何を意味しますか? 質問する

GCC が mov %eax,%eax を生成したのはなぜですか? また、これは何を意味しますか? 質問する

GCC 4.4.3 は、次の x86_64 アセンブリを生成しました。混乱している部分は、 ですmov %eax,%eax。レジスタをそれ自体に移動しますか? なぜですか?

   23b6c:       31 c9                   xor    %ecx,%ecx        ; the 0 value for shift
   23b6e:       80 7f 60 00             cmpb   $0x0,0x60(%rdi)  ; is it shifted?
   23b72:       74 03                   je     23b77
   23b74:       8b 4f 64                mov    0x64(%rdi),%ecx  ; is shifted so load shift value to ecx
   23b77:       48 8b 57 38             mov    0x38(%rdi),%rdx  ; map base
   23b7b:       48 03 57 58             add    0x58(%rdi),%rdx  ; plus offset to value
   23b7f:       8b 02                   mov    (%rdx),%eax      ; load map_used value to eax
   23b81:       89 c0                   mov    %eax,%eax        ; then what the heck is this? promotion from uint32 to 64-bit size_t?
   23b83:       48 d3 e0                shl    %cl,%rax         ; shift rax/eax by cl/ecx
   23b86:       c3                      retq   

この関数の C++ コードは次のとおりです。

    uint32_t shift = used_is_shifted ? shift_ : 0;
    le_uint32_t le_map_used = *used_p();
    size_t map_used = le_map_used;
    return map_used << shift;

le_uint32_t、ビッグエンディアン マシンでのバイトスワップ操作をラップするクラスです。x86 では何も行いません。このused_p()関数は、マップのベース + オフセットからポインターを計算し、正しい型のポインターを返します。

ベストアンサー1

x86-64では、32ビット命令は暗黙的にゼロ拡張されます。ビット32-63はクリアされます(誤った依存関係を避けるため) そのため、奇妙に見える説明が表示されることがあります。mov %esi, %esi は x86-64 では何も実行されませんか?

ただし、この場合、前のmov-load も 32 ビットなので、 の上位半分は%raxすでにクリアされています。 はmov %eax, %eax冗長であるように見えますが、どうやら GCC が最適化を逃しただけのようです。

おすすめ記事