将变量从 C 代码传递到 Assembly 并返回的正确语法是什么?

What is proper syntax to pass variables from C code to Assembly and back?

苦苦挣扎的电气工程专业学生尝试 link C 和汇编 (ARM32 Cortex-M) 嵌入式系统最终项目。我不完全理解这个项目的正确语法。

我被指示结合之前的 2 个实验 - 以及额外的代码 - 在 MBED 环境中使用 C 和汇编语言构建一个简单的计算器 (+,-,*,/)。我已将 C 文件设置为扫描键盘,将 3 个用户输入输入到 3 个字符串,然后将这些字符串传递到一个程序集文件。 Assembly 文件用于执行算术函数并将结果保存在 EXPORT PROC 中。然后,我的 C 文件将结果和 printf 提供给用户(我们使用 PuTTY 读取)。

这是我的程序集 header 并导入 links:

    AREA calculator, CODE, READONLY ; assembly header

compute_asm
          IMPORT OPERAND_1 ; imports from C file
          IMPORT OPERAND_2 ; imports from C file
          IMPORT USER_OPERATION ; imports from C file
          ALIGN ; aligns memory

initial_values PROC 
          LDR R1, =OPERAND_1; loads R1 with OPERAND_1
          LDR R2, =OPERAND_2; loads R2 with OPERAND_2 

这里有几行从我的 C 文件 link 到汇编:

int OPERAND_1; //declares OPERAND_1 for Assembly use
int OPERAND_2; //declares OPERAND_2 for Assembly use
int USER_OPERATION; //declares USER_OPERATION for Assembly use

extern int add_number(); //links add_number function in Assembly
extern int subtract_number(); //links subtract_number function in Assembly

我希望能够编译和使用这段代码(之前的实验比这个项目顺利得多)。但是在解决了一些其他语法问题之后,我得到了 "Error: "/tmp/fOofpw",第 39 行:警告:#47-D:编译时宏 "MBED_RAM_SIZE" 的重新定义不兼容。

编码是我的弱项。任何帮助或指点将不胜感激!

通常,特定版本的编译器针对特定目标使用的调用约定特定于该编译器和版本。并且技术上随时可能发生变化(即使我们已经看到了 gnu 和 arm)并且没有理由期望任何其他编译器符合相同的约定。尽管像 gcc 和 clang 这样的编译器符合 arm 推荐的 abi 的某些版本,但随着时间的推移,abi 已经发生了变化,gcc 也随之发生了变化。

正如彼得指出的那样:

LDR R1, =OPERAND_1; loads R1 with OPERAND_1

(您显然没有使用 gnu 汇编器,所以 gnu 工具链不正确?可能是 Kiel 或 ARM?)

将该标签的地址放入r1中,得到你需要的内容再加载

ldr r1,[r1]

现在内容就在那里。

使用全局变量可以解决调用约定问题。

使用一个简单的例子和​​反汇编你可以发现你的编译器的调用约定:

extern unsigned int add ( unsigned int, unsigned int);
unsigned int fun ( void )
{
    return(add(3,4)+2);
}
00000000 <fun>:
   0:   b510        push    {r4, lr}
   2:   2104        movs    r1, #4
   4:   2003        movs    r0, #3
   6:   f7ff fffe   bl  0 <add>
   a:   3002        adds    r0, #2
   c:   bd10        pop {r4, pc}
   e:   46c0        nop         ; (mov r8, r8)

第一个参数在 r0 中,第二个在 r1 中,return 在 r0 中。这在技术上可能会在任何版本的 gnu 上发生变化,但可以告诉你从 gcc 2.x.x 到现在的 9.1.0 这就是 arm 的情况。 gcc 3.x.x 到现在的 thumb 就是你正在使用的。

您的做法很好,您只需要了解 =LABEL 快捷方式的真正作用即可。