河野真治 @ 琉球大学情報工学です。

Mac OS X の gcc コンパイラのアセンブラ出力を眺めていたんです
が... 

Relocatable つまり、コードの位置をリンク時に決めない方式なの
で、サブルーチンの先頭に、自分のコードの位置を知るために、

0x19d9c <__i686.get_pc_thunk.bx>:       mov    (%esp),%ebx
0x19d9f <__i686.get_pc_thunk.bx+3>:     ret    

とかいうのを呼んでいる。もちろん、メモリ上の固定数値も呼ばず、
大域変数にもアクセスしなければ、呼ぶ必要はないわけだけど。し
かも、この位置を記憶するEBXレジスタは、ずーっと、潰れること
になる。

で、大域変数は、
         leal    L_uc1$non_lazy_ptr-"L00000000006$pb"(%ebx), %eax
         movl    (%eax), %eax
         movb    $-56, (%eax)
でアクセスすることになる。だから、一旦ポインタに入れないと大域変数にアクセスで
きない。
         movl    L_uc1$non_lazy_ptr-"L00000000006$pb"(%ebx), %eax
         movb    $-56, (%eax)
これでもいいのか。

ってことは、大域変数にアクセスする時は、6個しかないia32の汎
用レジスタのうち2つは、必ず、潰れているってことだね。ま、い
いんだけど。ia32 には、わり算するときにはEDXがつぶれるという
楽しい技もあるんだよな。 32個レジスタあるってならともかく。

なんか、昔の MC6800 を使ったアセンブラプログラミングみたい。
MC6800はポインタ一つ、アキュームレータ一つだったから。これで、
そこそこ速く動くCPUだってのが奇跡だ... 仮想レジスタの威力な
のかなぁ。get_pc_thunk.bx みたいなので、実メモリにアクセスし
ていたんじゃだめだめそうなものなんだが。

もちろん、大域最適化をすれば、このあたりはだいぶましにはなる
んだけど。あぁ、たくさん文字列定数を使うときには、先にまとめ
て、取得して局所変数に入れておくみたいなことするのかぁ。

         leal    LC143-"L00000000027$pb"(%ebx), %edi
         movl    %edi, -660(%ebp)
         leal    LC144-"L00000000027$pb"(%ebx), %eax
         movl    %eax, -664(%ebp)
         leal    LC145-"L00000000027$pb"(%ebx), %edi
         movl    %edi, -668(%ebp)
         leal    LC146-"L00000000027$pb"(%ebx), %eax
         movl    %eax, -672(%ebp)
         leal    LC147-"L00000000027$pb"(%ebx), %edi
         movl    %edi, -676(%ebp)
         leal    LC148-"L00000000027$pb"(%ebx), %eax
         movl    %eax, -680(%ebp)
なにやってるのかと思ったよ... その方がEBXが空くから有利って
ことなんだろうな。大域最適化の結果がこれかよ。

なんで、こんなCPUが流行ってしまったのか。

---
Shinji KONO @ Information Engineering, University of the Ryukyus
河野真治 @ 琉球大学工学部情報工学科