コンパイルされたすべてのコードが位置に依存しないのはなぜですか?

間接を追加します。位置に依存しないコードでは、関数のアドレスをロードしてからジャンプする必要があります。通常、関数のアドレスは命令ストリームに既に存在します。


はい、パフォーマンス上の理由があります。一部のアクセスは、メモリ内の絶対位置を取得するために、効果的に別の間接レイヤーの下にあります。

また、グローバル変数のオフセットを格納する GOT (グローバル オフセット テーブル) もあります。私には、これは IAT フィックスアップ テーブルのように見えます。これは、ウィキペディアや他のいくつかの情報源によって位置に依存するものとして分類されています。

http://en.wikipedia.org/wiki/Position_independent_code


受け入れられた答えに加えて。 PIC コードのパフォーマンスを大きく低下させる原因の 1 つは、x86 での「IP 相対アドレス指定」の欠如です。 「IP相対アドレッシング」を使用すると、現在の命令ポインターからXバイトのデータを要求できます。これにより、PIC コードが大幅に簡素化されます。

ジャンプと呼び出しは通常 EIP に関連しているため、実際には問題になりません。ただし、データへのアクセスには、ちょっとした工夫が必要です。場合によっては、コードが必要とするデータへの「ベース ポインター」として、レジスターが一時的に予約されることがあります。たとえば、一般的な手法は、x86 での呼び出しの動作を悪用することです:

call label_1
.dd 0xdeadbeef
.dd 0xfeedf00d
.dd 0x11223344
label_1:
pop ebp            ; now ebp holds the address of the first dataword
                   ; this works because the call pushes the **next**
                   ; instructions address
                   ; real code follows
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way

この手法やその他の手法により、データ アクセスに間接的なレイヤーが追加されます。たとえば、gcc コンパイラで使用される GOT (グローバル オフセット テーブル)。

x86-64 は「RIP 相対」モードを追加し、物事をロットにします