eiz レジスタ?

さらに続き。
もう飽きてきたころに、なんで C のほうが速いんだろうってことで objdump で逆アセンブルしてみたときに見つけた変なレジスタ

4017a5:	8d 74 26 00          	lea    0x0(%esi,%eiz,1),%esi
4017a9:	8d bc 27 00 00 00 00 	lea    0x0(%edi,%eiz,1),%edi
4017b0: ...

Intel形式なら lea edi, [edi + eiz + 0] でしょうか。

eiz レジスタ?ぐぐってみると Add fake index registers, EIZ/RIZ, to x86 assembler/disassembler. だそうで、フェイクらしい。命令フォーマットを読み解いてみると、8d が LEA のオペコード、ModR/M が 74 なので デスティネーションが esi、SIB が 26 なので esi + none、ディスプレースメントが 0。というわけで、インデックスレジスタの指定なしを表してるようです。

さらに、この2つの命令は実行しても何も変わりません。CPU時間を食うのと、スペースを食うだけです。 gcc で -O3 をつけてコンパイルした結果なのになんでこんなのが挟み込まれるのかと思ったら、http://gcc.gnu.org/ml/gcc/2007-03/msg00817.html によるとアラインメント調整だそうです。なるほど納得。命令フェッチが16バイト境界に揃ってると有利とかなんとかありましたね。この2つの命令の次のアドレスがきっちり揃っています。

アセンブルしたコードを見てみると、あちこちにこの命令のバリエーションが挟み込まれています。上の例でも 4byte と 7byte の2つがありますが、ほかに 3byte (8d 76 00 lea 0x0(%esi),%esi)、6byte (8d b6 00 00 00 00 lea 0x0(%esi),%esi) もありました。一つだけ使ったり、上のように二つ並べたりしてます。
いずれも次の命令がきっちり 16byte 境界に揃っていました。ジャンプなどの飛び先を 16byte 境界にそろえているようです。

でも、必ずしも飛び先アドレスが 16byte 境界にそろってるわけでもないので、飛んだ先に十分な命令があれば調整しないとかしてるんでしょうかねぇ。まあ、とにかく、コンパイラには私はかないそうもないとわかりましたw

以上、アセンブラな記録はおしまい。