Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
控制功能';arm gcc中的s预记录和epilog_C_Gcc_Assembly_Arm - Fatal编程技术网

控制功能';arm gcc中的s预记录和epilog

控制功能';arm gcc中的s预记录和epilog,c,gcc,assembly,arm,C,Gcc,Assembly,Arm,我注意到,有时在编译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,它导致了一个严重的问题。

我注意到,有时在编译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

1) 您可以手动保存它,因为您编写了内联程序集,所以您可以在调用函数之前保存LR,并在调用之后恢复它

2) 您可以声明一个虚拟变量,该变量将使用以下C代码放入LR中:

register int foo asm ("lr");
3) 使用


请注意,最好的解决方案可能是第三个。

lr
标记为clobbred,以使编译器保存它:

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

有关更多详细信息,请参阅。记住,也要将您使用的所有其他寄存器标记为clobbered。否则,编译器可能会在其中一个中放入一个变量。您可能还需要将所有调用者保存的寄存器标记为clobbered。

最简单/直接的答案是将
lr
添加到clobber,但您可能需要添加更多


为什么??

编译器根据函数的类型生成不同的序言/尾声。它们可以是泛型函数、叶函数(不调用其他函数)或尾部调用。您没有显示任何代码,因此很难了解您的具体情况。然而,如果您没有记录内联汇编程序正在调用另一个函数,那么gcc认为它是一个叶函数,而不是

在不使用输入/输出操作数的情况下访问C程序中的数据(例如直接使用汇编程序模板中的全局符号)可能无法按预期工作。类似地,直接从汇编程序模板调用函数需要详细了解目标汇编程序和ABI

出于这个原因,我认为将
r0
-
r3
lr
添加到缓冲区也是最安全的。也可能需要霓虹灯/浮点寄存器。编译器应该知道,这些可以通过“inline
asm
”语句进行更改

如果在汇编语句之后没有代码,并且假设没有使用“帧指针”或其他寄存器,则可以使用尾部调用。即,将
bl inline\u asm\u target
替换为
b inline\u asm\u target
,其中inline\u asm\u target函数仍然执行
bx lr
(或任何适合使用的编译器选项/ABI的操作)

相关:
-

-

为什么在没有显示函数在C中的外观的情况下,就将问题标记为“C”?最好将在内联汇编中完成的调用替换为在C中完成的调用。如果您需要汇编来获取SP,则使用它来获取SP;调用是不相关的,所以在C中进行。这应该不难,但您没有显示代码,因此我们无法知道。在C中的等价物是编写“int func(){}”,因为我谈到了函数prelog。但既然这没有提供任何信息,我觉得这没有什么意义。@YouYou,我很高兴。