我注意到有时当我编译C代码时,有时会在方法1中生成汇编代码:
STR R11, [SP, #-4]!
ADD R11, SP, #0
SUB SP, SP, #4
有时使用方法 2:
STMFD SP!, {R11, LR}
ADD R11, SP, #4
SUB SP, SP, #4
第一种方法和第二种方法的区别在于第二种方法将LR保存到栈中。
现在我面临一个问题,我的函数像第一个方法一样启动,使用链接寄存器(BL)调用另一个函数,并且由于我的函数首先不保存LR,所以会导致严重的问题。 如果我可以告诉编译器使用第二种方法它可以解决我的问题。
这可能与该函数使用内联汇编调用内部函数这一事实有关,因此“无法识别”存在对另一个函数的调用,并且认为保存 LR 没有意义。调用内联汇编是必须的,因为被调用的函数获取 SP 的值作为参数。
这是一个相当棘手的问题,希望有人能帮助我解决这个问题。 谢谢!
最佳答案
将 lr
标记为破坏以使编译器保存它:
extern void foo(void);
extern void bar(void)
{
asm ( "bl foo" : : : "lr" );
}
生成以下代码:
bar:
str lr, [sp, #-4]!
bl foo
ldr lr, [sp], #4
bx lr
参见the documentation更多细节。请记住将您使用的所有其他寄存器也标记为已损坏。否则,编译器可能会将变量放入其中之一。您可能还需要将所有调用者保存的寄存器标记为已损坏。
关于在arm gcc中控制函数的prelog和epilog,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37562932/