挣扎的电气工程专业学生试图将C和Assembly(ARM32 Cortex-M)链接在一起,以完成嵌入式系统的最终项目。我不完全了解此项目的正确语法。
我被指示结合了之前的两个实验以及其他代码,以在MBED环境中使用C和汇编语言构建一个简单的计算器(+,-,*,/)。我已将C文件设置为扫描键盘,将3个用户输入输入3个字符串,然后将这些字符串传递给Assembly文件。汇编文件用于执行算术功能并将结果保存在EXPORT PROC中。然后,我的C文件将结果和printf带给用户(我们使用PuTTY读取)。
这是我的程序集头和导入链接:
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文件中,有几行链接到Assembly:
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
我希望能够编译和使用此代码(以前的实验比该项目要顺利得多)。但是在解决了一些其他语法问题之后,我得到了“错误:“ / tmp / fOofpw”,第39行:警告:#47-D:编译时宏“ MBED_RAM_SIZE”的重新定义不兼容。
编码是我的弱点。任何帮助或指示,将不胜感激!
答案 0 :(得分:2)
通常,特定版本的编译器针对特定目标使用的调用约定特定于该编译器和版本。从技术上讲,它随时都可能发生变化(即使我们已经看到了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中的第二个参数,在r0中返回。从技术上讲,将来的任何版本的gnu都可能会发生变化,但是可以告诉您从gcc 2.x.x到现在的9.1.0,这就是arm的工作方式。 gcc 3.x.x到现在为止,这就是您正在使用的拇指。
您的工作方式很好,您只需要了解= LABEL快捷方式的实际作用即可。