【问题标题】:Register usage in ARM assembly function which is called by a C functionC 函数调用的 ARM 汇编函数中的寄存器使用情况
【发布时间】:2020-12-14 23:19:08
【问题描述】:

ARM 的 C 函数调用约定说:

  • 调用者将传递 r0-r3 中的前 4 个参数。
  • 调用者将在堆栈上传递任何额外的参数。
  • 调用者将从 r0 获取返回值。

我正在手工制作一个由C调用的汇编函数,原型等价于:

void s(void);

假设一个 C 函数 c() 调用 s()

因为s() 没有参数也没有返回值。我相信r0-r3不会被编译器触动生成c()调用s()的调用序列。

假设s() 将使用r0-r12 来完成它的功能。 c() 也有可能使用这些寄存器。

我不确定是否必须明确保存和恢复s() 中涉及的所有寄存器,例如r0-r12。这样的内存操作会花费一些时间。

或者至少我不必为r0-r3这样做?

【问题讨论】:

  • void s() 表示“接受任何参数”并且是过时的样式。请改用void s (void)
  • @Lundin 哦,我没有意识到这一点。谢谢提醒。已更新。

标签: c gcc arm calling-convention


【解决方案1】:

来自Procedure Call Standard for the Arm Architecture,第 6.1.1 节(第 19 页):

子程序必须保留寄存器 r4-r8、r10、r11 和 SP(以及将 r9 指定为 v6 的 PCS 变体中的 r9)的内容

所以是的,因为 r0-r3 是暂存寄存器,所以在 s() 中使用它们之前不需要保存它们,但你必须保存和恢复任何其他寄存器。

假设编译器与 ARM ABI 兼容,则像这样声明 s()

extern void s(void);

应该足够了,并且编译器不应该在调用s()之后发出依赖于c()函数中r0-r3先前值的代码(即c()应该在调用@之前保存r0-r3,如果需要的话987654328@ 并在之后恢复它们),因为这会破坏 ABI 合规性。

【讨论】:

    【解决方案2】:

    通常在混合 C 和 asm 时,您永远不能对 C 代码使用的寄存器做出任何假设,除了那些保证会被调用约定堆叠的寄存器。在使用它们之前堆叠所有其他寄存器,然后再弹出它们。所有这一切都取决于编译器在调用您的汇编程序函数时所做的和内部不做的假设。

    这里有一些很好的信息:Mixing C, C++, and Assembly Language

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 2013-02-09
      相关资源
      最近更新 更多