2012-08-10 8 views
23

GCC 4.4.3が次のx86_64アセンブリを生成しました。私を混乱させる部分はmov %eax,%eaxです。レジスタを自分自身に移動しますか?どうして?なぜGCCは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()関数は、マップの基数+オフセットからポインタを計算し、正しい型のポインタを返します。

+2

参照http://stackoverflow.com/questions/2703394/whats-the-point-of-lea-eax-eax – nos

+0

@nos:おそらく。しかし、GCCはどんな理由でそこにノブを望んでいますか?整列するものは何もありません。 –

+0

SHL命令のアドレスは1バイトにのみ整列されます(次の命令に着地する必要がない場所にジャンプする)何かがあったとしても、そうではありません。これはちょうどオプティマイザのバグのようです。別のフラグと最近のバージョンのgcc(4.4.3はかなり古くなっています)を試してみて、どのような効果があるかを見てください。 –

答えて

22

x86-64では、32ビット命令は暗黙的にゼロ拡張です。ビット32-63がクリアされます。だから時々、あなたは奇妙に見える指示を見るでしょう。

ただし、前のmovも32ビットであるため、%raxの上位半分はすでにクリアされています。 mov %eax,%eaxはNOPのようです。

+0

この種類のNOPもパイプライン最適化の目的に役立ちます。 – mathk

関連する問題