我正在尝试使用C中的内联汇编为powerpc64编写一个简单的函数,我的函数调用另一个函数,我有几个与之相关的问题。
1)如何在使用' bl'分支之前保存LR寄存器?到子程序?
具体来说,对于此代码:
void func(void *arg1, void *arg2)
{
void *result;
__asm__ volatile (
...
...
"bl <address>\n" //Call to subroutine
"nop\n"
...
: [result]"=r"(result)
: [arg1]"r"(arg1),
[arg2]"r"(arg2)
);
return result;
}
编译器为此生成序言代码而没有&#34; mflr 0; std 0,16(1)&#34;保存LR的指令,因为它不知道我的汇编代码中正在调用子程序。我是否在汇编代码中包含这些说明?如果是这样,我怎么知道编译器序言代码创建的堆栈大小到达函数调用&#39; func&#39;?的LR保存区域? (从developerWorks上的powerpc汇编教程中,LR寄存器需要保存在&#39;调用&#39;函数的堆栈框架中)
2)我相信在调用子程序之前我需要保存arg1和arg2,这是在进行子程序调用之前临时存储这些参数的正确位置 - 参数保存区域还是非易失性寄存器?我只是想知道这是在生产质量ppc64代码中完成的正确方法
提前致谢!
答案 0 :(得分:1)
AFAIK没有办法正确地做到这一点。内联asm不是为调用函数而设计的。
您无法可靠地知道编译器生成的堆栈帧的大小,实际上整个函数可能是内联的,或者您认为编译器可能根本不会生成堆栈帧。
但是你没有 将LR存储在调用者堆栈框架中,如果你这样做最好,但不是100%要求。所以只需将它放在一个非易失性标记中,注册为破坏标记,并在返回途中恢复它。
您不需要保存arg1和arg2,但您必须做的是将所有易失性寄存器标记为已破坏。然后编译器将在调用asm之前保存易失性寄存器中的任何内容(如arg1和arg2)。还要记住,某些CR字段可能会被破坏。我还要给“clobbers”添加“记忆”,以便GCC对整个asm的优化感到悲观。
如果你做了可能的所有工作,除非我忘记了一些事情:)