我正在阅读有关Linux here上的MIPS的PIC实现。它说:
存储在$ gp寄存器(又名$ 28)中的全局指针是被调用者保存的寄存器。
Wikipedia article about MIPS说的一样。
然而,根据他们的说法,当在函数序言中使用.cpload
指令时,它会先破坏$ gp的先前值而不先保存它。当使用.cprestore
时,它会将当前 $ gp保存到堆栈帧,而不是函数入口处的$ gp值。 .cprestore
对jal
/ jalr
的影响也是如此:一旦被调用者返回,它就会恢复$ gp - 假设被调用者可能已经破坏了它。
最后,关于$ gp的函数结尾没有任何内容。
总而言之,听起来不像被叫方保存的寄存器给我。听起来像是来电者保存的寄存器。我在这里误解了什么?
答案 0 :(得分:0)
MIPS上的Linux程序可以编写为pic或不编辑。如果编译为pic,那么他们必须使用" abicalls",并且它的行为与no-abicalls惯例的行为略有不同。
来自"部分位置无关功能序言" " SYSTEM V应用程序二进制接口 - MIPS处理器补充第3版"我们可以引用:
计算gp后,函数会分配本地堆栈空间并将gp保存在堆栈中,因此可以在后续函数调用后恢复。换句话说,gp是一个调用者保存的寄存器。
下图中的代码说明了与位置无关的函数序言。 _gp_disp表示函数开头和全局偏移表之间的偏移量。
name: la gp, _gp_disp addu gp, gp, t9 addiu sp, sp, –64 sw gp, 32(sp)
总而言之,如果您正在使用-mabicalls
,那么gp
会在所有需要全局符号的函数(有一些例外)的开头计算,另外还有任何代码(abi或不)调用abi代码将确保被调用的函数地址存储在t9
。