ロード時の再配置と仮想メモリのサポートは、2 つの異なる概念です。最近のほとんどすべての CPU と OS は、仮想メモリをサポートしています。仮想メモリについて理解すべき唯一の本当に重要な点は、物理アドレスを忘れることです。これは現在、ハードウェアと OS の責任であり、ページング システムを作成している場合を除き、物理アドレスを忘れることができます。プログラムが使用するすべてのアドレスは仮想アドレスです。これは大きな利点であり、プログラミング モデルが大幅に簡素化されます。0x0000000032 ビット システムでは、これは単純に、各プロセスが からまでの範囲の独自の 4 GiB メモリ空間を取得することを意味します0xffffffff。
An.exeはプロセスを表します。リンカはファイルから生成.exeし.objます。どちらもバイナリ ファイル.objですが、すべての変数と関数のアドレスが含まれていないため、ファイルは実行可能ではありません。これらのアドレスを提供するのはリンカの仕事です。リンカは、これらの.objファイルを端から端まで配置し、すべてのシンボル (関数と変数) の正確なアドレスを計算することによって決定します。したがって、.exe作成される には、関数と変数のすべてのアドレスが「ハードコーディング」されています。ただし、 を作成する前に必要な重要な情報が 1 つあり.exeます。リンカーは、メモリ内のどこにロードされるかについての内部知識を持っている必要があり.exeます。それはアドレス0x00000000にありますか、それともにありますか0xffff0000、または他の場所?たとえば、Windows では、すべて.exeの は常に の絶対開始アドレスにロードされます0x00400000。これをベースアドレスと呼びます。リンカーは、シンボル (関数と変数) の最終アドレスを生成するときに、このアドレスからそれらを計算します。
現在、.exes を他のアドレスにロードする必要はほとんどありません。しかし、.dlls についてはそうではありません。.ddls は s と同じ.exeです (どちらも移植可能な実行可能 (PE) ファイル形式でフォーマットされており、たとえば、テキストがどこにあるのか、データがどこにあるのか、どちらを見つける方法など、メモリ レイアウトが記述されています)。.dllにも優先アドレスがあります。これは単に、リンカが .xml 内のシンボルのアドレスを計算するときにこの値を使用することを意味します.dll。.dllがこのアドレスにロードされていれば、準備は完了です。
しかし、他のものがこのアドレスに既にロードされているため.dllに、このアドレスに をロードできない場合 ( だったとします)、ローダーはメモリ内の他のスペースを見つけてそこに をロードします。ただし、 の関数とシンボルのグローバル アドレスは正しくありません。したがって、ローダーは再配置(「フィックスアップ」とも呼ばれます) を実行する必要があります。この再配置では、すべてのグローバル シンボルと関数のアドレスを実際のアドレスを反映するように調整します。0x10000000.dll.dll.dll
この調整を行うために、ローダーは.dll. PE ファイルには、.relocそのようなすべてのシンボルの内部オフセットを含むセクションがあります。
もちろん、他の詳細もあります。たとえば、コンパイラがコードを生成したときに間接呼び出しを使用して、直接呼び出しを行う代わりに、呼び出しが間接的であり、.exe.
最後に、要点は次のとおりです。コードが予想された位置 (4 GiB アドレス空間内) にロードされない場合は、呼び出しとジャンプのアドレスと変数アクセス命令を調整するために、(何らかの) 再配置が必要です。ロード。OS.exeが.exe.