首页 > 解决方案 > 如何定义可在 C 中使用的 ARM 汇编函数

问题描述

我已经学习 C 几个月了,现在我开始更深入地研究低级语言 - ARM 汇编,所以,我决定从一个非常基本的项目开始,制作一个汇编文件 .S 定义一个阶乘函数,然后在C中调用和使用。所以我想问一下是否可以使用汇编来定义这样一个复杂的函数,并且可以用作C中的另一个函数?如果您不介意,请给我一个简单的 .S 文件示例,其中一个函数从标准输入 num1 和 num2 加载 2 个数字到寄存器,计算 num1*num2 并返回定义的结果,可以在 C 源代码中使用文件?

感谢您的阅读。如果这个问题是愚蠢的,至少,请给我一个方向,以便我可以自己跟随并找出它。

标签: assemblyarmgnu-toolchain

解决方案


要从 C 中使用用 Assembler 编写的函数,您主要需要:

  1. 在 C 中声明但不定义函数。
  2. 坚持 ARM 调用约定。

宣言

声明很容易,例如:

int add(int a, int b);

这是一个声明,因为它不包括函数体。当然,名称(在本例中为add)必须匹配。

如果在 C++ 中使用它,则必须添加extern "C"

extern "C" int add(int a, int b);

调用约定

调用约定定义了如何将参数传递给函数并从函数返回,以及必须保存哪些寄存器。你需要熟悉细节。可以在ARM (A32) 调用约定中找到简化的概述。

一个超短且非常简化的版本是:

  • 前四个参数在 R0 中传递给 R3,其余的在堆栈中传递。
  • 返回值在 R0 中返回。
  • 必须保存和恢复 R0 至 R3 以外的寄存器。

上述函数的一个简单实现是:

add:
        add     r0, r0, r1
        bx      lr

a在 R0b中通过,在 R1 中通过。结果以R0. R3 以上的寄存器不会被保存和恢复,因为它们没有被触及。

更广泛的版本如下所示:

add:
        str     fp, [sp, #-4]!
        add     fp, sp, #0
        sub     sp, sp, #12
        str     r0, [fp, #-8]
        str     r1, [fp, #-12]
        ldr     r2, [fp, #-8]
        ldr     r3, [fp, #-12]
        add     r3, r2, r3
        mov     r0, r3
        add     sp, fp, #0
        ldr     fp, [sp], #4
        bx      lr

它基本上是add函数的调试版本:在堆栈上分配空间来存储并作为局部变量,帧指针寄存器 (fp) 指向局部变量。最后,一切都恢复了。ab


推荐阅读