我正在使用ARM程序集,我必须编写一个子程序,我遵循ARM调用约定(这必须与某个单独的更高级别实现集成其他)传递参数和返回值。现在,这是我在使用程序集时通常不确定的事情。在程序集中传递子程序的参数和返回值
所以根据约定,如果我理解得很好,参数将按顺序从寄存器r0 - r4开始传递,然后使用其他参数堆栈。返回值传递给r0。
现在,这是我很困惑。如果我应该保存r0的上下文并在此之后弹出它,则无法返回结果,唯一的办法是破坏第一个参数。有什么解决方法吗? 在此先感谢你们!
我正在使用ARM程序集,我必须编写一个子程序,我遵循ARM调用约定(这必须与某个单独的更高级别实现集成其他)传递参数和返回值。现在,这是我在使用程序集时通常不确定的事情。在程序集中传递子程序的参数和返回值
所以根据约定,如果我理解得很好,参数将按顺序从寄存器r0 - r4开始传递,然后使用其他参数堆栈。返回值传递给r0。
现在,这是我很困惑。如果我应该保存r0的上下文并在此之后弹出它,则无法返回结果,唯一的办法是破坏第一个参数。有什么解决方法吗? 在此先感谢你们!
当您返回r0的返回值时,调用者预计您将执行此操作。调用者不会期望r0仍然包含与原始第一个参数相同的值,因为r0特别是返回值所在的位置。
正常情况下,ARM calling convention requires that the subroutine preserves r4 through r11,而不是r0到r3。所以没有任何矛盾。
为什么不自己尝试一下,看看编译器做了什么?
unsigned int fun (unsigned int a, unsigned int b)
{
return(a+b);
}
编译到对象和拆卸
arm-none-eabi-gcc -O2 -c fun.c -o fun.o
arm-none-eabi-objdump -D fun.o
,其结果是
00000000 <fun>:
0: e0810000 add r0, r1, r0
4: e12fff1e bx lr
两个输入a和b在使用r0和r1被传递。 r0-r4不必保存,特别是r0因为它的返回值无法保存。因此,所需的C代码将两个操作数相加,并且由于调用约定要求结果返回r0。 r0 = r0 + r1。
编译器必须符合惯例,否则它生成的代码将无法正常工作,因此您可以简单地编译代码并反汇编以查找相当多关于特定编译器和目标的调用约定。
所以我想调用者有责任在调用函数之前保存r0的上下文。 – as3rdaccount
从您发布的链接:*“r0到r3:用于保存传递给子例程的参数值,并保持从子例程返回的结果”*。 – m0skit0