前の記事の通り、アセンブルは正常に完了するようになったのですが、今度はちゃんとリンクできません。

こんなエラーが出ます。

ld: absolute addressing (perhaps -mdynamic-no-pic) used in _x86_sse2_ConvertULY2ToBottomupRGB24.label1 from /Users/umezawa/proj/utvideo/build/utvideo.build/Release/utvideo.build/Objects-normal/i386/Convert_asm_x86.o not allowed in slidable image. Use ‘-read_only_relocs suppress’ to enable text relocs

該当箇所のコードはおおむね以下のようになっています。メモリアドレスを(レジスタからのオフセットなどではなく)絶対指定しているのがいけない、と言われているわけですね。

        align   64
;                fedcba9876543210
yoff    dq      00010001000100010h
        dq      00000000000000000h
(略)
_x86_sse2_ConvertULY2ToBottomupRGB24:
(略)
.label1:
        pxor            xmm3, xmm3
        movd            xmm0, dword [ebp]
        punpcklbw       xmm0, xmm3
        psubw           xmm0, oword [yoff]
        punpcklwd       xmm0, xmm3

これを解消するには PIC (Position Independent Code) にする必要があるのですが、Windows の住人からするとそんな下らないことは(コードを書き換えるのではなく)ダイナミックローダーが解決しろよと思うわけです。Visual C++ には PIC にするコンパイラオプションは無く、DLL をロードする時に全部解決されます。x86 で PIC にすると eip レジスタを汎用レジスタにコピーするために call と pop をする珍妙なコードが出力され、これは現代的なプロセッサでは恐らく大幅にパフォーマンスダウンします。x64 だとこのあたりを解決するために RIP 相対アドレッシングが導入されたわけですが。

こんなもんに付き合うつもりは無いので、エラーメッセージで提示されている通り “-read_only_relocs suppress” をリンカオプションに付けることにします。ビルドターゲットの「情報を見る」の「ビルド」タブの中の「リンク」の下の「他のリンカフラグ」に追加します。これでリンクできるようになります。

で、できたバイナリがちゃんと実行できるかどうかですが、ちょろっと試した限りでは正常に動いています。たぶん、バイナリをメモリ上で書き換えるためにロードに時間がかかる以外は、別段の問題は発生しないのでしょう。

Trackback

no comment untill now

Add your comment now