「コンピュータ システム: プログラマの視点」セクション 7.7.1 再配置エントリを読むとき: このセクションの簡単な内容は、リンカが別のオブジェクト ファイルで参照を再配置する方法です。
サンプル ソース コードをコンパイルして objdump すると、次のようになります。
void swap();
int buf[2] = {1, 2};
int main()
{
swap();
return 0;
}
次に、gcc -Wall -c -o main.o main.c、および objdump -S -r main.o > main.asm; スワップの再配置エントリが表示されます。
6: e8 fc ff ff ff call 7 <main+0x7> swap();
7: R_386_PC32 swap relocation entry
したがって、ld が main.o と swap.o をリンクするとき、ld は swap(offset=7, type=R_386_PC32) の再配置エントリ r を使用して、リンク アドレスを決定します。
refaddr = ADDR(section .text) + r.offset
*refptr = (unsigned)(ADDR(r.symbol + *refptr - refptr)
また、call 命令のオペランド (fc ff ff ff) -4 は、386 命令セットに完全に適合しています。
しかし、X86_64 Linux でこれを繰り返すと、呼び出しのコードは次のようになります。
9: e8 00 00 00 00 callq e <main+0xe>
a: R_X86_64_PC32 swap relocation entry
次に、私の質問は、386 の call(e8) のオペランドが -4((fc ff ff ff) であるのに、X86_64 の main.o のオペランドが 00 00 00 00 である理由です。異なる命令セット (call vs .callq)、または単に GNU ld が別のアルゴリズムを使用して R_X86_64_PC32 を再配置しますか?
あなたが答えてくれることを願っています、どうもありがとう。