堆栈和链接寄存器如何在中断过程中使用? (ARM处理器)

时间:2015-04-16 20:06:38

标签: exception arm cpu-registers

ARM网站说链接寄存器存储子程序,函数调用和异常(例如中断)的返回信息,那么用于什么堆栈?

this similar question的答案表示堆栈用于存储返回地址,并“推送”局部变量,这些变量需要在异常后返回核心寄存器。

但这是链接寄存器的用途,为什么需要呢?这两者之间有什么区别?它们是如何使用的?

1 个答案:

答案 0 :(得分:1)

好的,我想我理解你的问题。

所以你在函数中有一些代码调用函数

main ()
{
int a,b;
a = myfun0();
b=a+7;
...

所以当我们调用myfun0()时,链接寄存器基本上会让我们回来,所以我们可以做b = a + 7;理解当然所有这些都被编译成汇编和优化等等,但这足以理解链接寄存器用于在调用之后返回。

但是如果

myfun0 ()
{
return(myfun1()+3);
}

当main调用myfun0()时,链接寄存器指向main()函数中需要返回的某些代码。然后myfun0()调用myfun1()它需要返回myfun0()在返回main()之前再做一些数学运算,所以当它调用myfun1()时,链接寄存器设置为返回并添加3.问题当我们设置链接寄存器以返回myfun0()时,我们将main()中的地址丢弃,我们需要返回。因此,为了防止 IF 该函数将调用另一个函数,以及不能存在于一次性寄存器中的局部变量,必须将链接寄存器放在堆栈中。所以现在主调用myfun0(),myfun0()将调用一个函数(myfun1()),因此链接寄存器的副本(将地址返回到main())保存在堆栈中。 myfun0调用myfun1()myfun1()遵循相同的规则,如果调用其他东西把lr放在堆栈上,否则你不必,myfun1()使用lr返回myfun0(),myfun0()从堆栈恢复lr所以它可以回到主要。按照每个功能的简单规则,你就不会出错。

现在中断不确定是否相关或者我误解了你的问题。因此,arm至少为非cortex-m核心存储了寄存器。但一般情况下,如果异常处理程序需要使用前台任务正在使用的任何资源/寄存器而发生中断/异常,那么该处理程序需要以这样的方式保留堆栈中的那些,使得被中断的前台任务具有不知道发生了这种情况,因为通常在任何两条指令之间都会发生中断,所以你甚至需要保留指令在你中断之前设置的标志。

所以将它应用于arm,你必须看看你正在使用哪个体系结构,看看它描述了中断过程在哪里你必须保留哪些寄存器,你不使用哪些寄存器,使用哪个堆栈指针等等(你有的东西)如果您正在使用具有单独中断堆栈和前向堆栈的臂,请在第一个例外之前进行设置。

cortex-m旨在为你做一些/全部工作它基本上有一个堆栈,并且在中断时它会为你推送堆栈上的所有寄存器,所以你只需要一个C编译函数就可以作为一个处理程序和硬件清理后(从保留的寄存器角度)。其他一些处理器系列为你做这样的事情,它们可能从中断指令返回而不是返回指令,一个是因为在中断时硬件保存标志和返回地址但是对于一个简单的调用,你不需要保留标志

手臂比其他一些指令集灵活得多,其他一些指令可能没有任何指令可以让你分支到任何你希望你可能有限制的寄存器中的地址。您可能会限制使用哪个寄存器作为堆栈指针,或者堆栈指针本身不能作为通用寄存器访问。根据惯例,sp在手臂中是13,它们允许push和pop的伪指令转换为正确的ldmia r13!{blah}和stmdb r13!,{blah}但是你可以选择你自己的(如果没有使用编译器)遵循约定或可以更改开源编译器以使用不同的堆栈指针寄存器)。手臂没有阻止这一点。链接寄存器r14的神奇之处只不过是分支链接或分支链接交换自动修改r14,但是指令集允许你基本上使用任何寄存器来分支/返回正常的函数调用。该臂具有足够的通用寄存器,以鼓励编译器仅执行基于寄存器的参数传递与堆栈。有些处理器倾向于只有堆栈参数传递,并且设计了它们的返回地址指令,严格地基于堆栈,避免一起返回寄存器,以及如果嵌套函数必须保存的规则。

所有这些方法都有利有弊,在arm寄存器传递的情况下也是可取的,也是基于寄存器的返回地址,但是对于嵌套函数,你必须保留每个嵌套级别的返回地址,以免丢失。同样地,对于中断,你必须以你发现它们的方式把东西放回去,并且能够回到你打断前景的地方。