当读本书计算机系统:程序员的角度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将使用交换的重定位项R(偏移= 7,类型= R_386_PC32),以确定链接地址:
refaddr = ADDR(section .text) + r.offset
*refptr = (unsigned)(ADDR(r.symbol + *refptr - refptr)
和调用指令(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呼叫(E8)的操作数为-4((FC FF FF FF),但在X86_64 main.o操作数是00 00 00 00?难道是因为不同的指令集(称之为VS 。callq),或仅仅是GNU LD使用不同的算法来搬迁R_X86_64_PC32?
希望能为你解答,非常感谢。