c - 将变量从 C 代码传递到汇编并返回的正确语法是什么?
问题描述
苦苦挣扎的电气工程专业学生试图将 C 语言和汇编语言 (ARM32 Cortex-M) 联系起来,以完成嵌入式系统的最终项目。我不完全理解这个项目的正确语法。
我被指示结合之前的 2 个实验 - 以及额外的代码 - 在 MBED 环境中使用 C 和汇编语言构建一个简单的计算器(+、-、*、/)。我已将 C 文件设置为扫描键盘,将 3 个用户输入输入到 3 个字符串,然后将这些字符串传递给程序集文件。汇编文件用于执行算术函数并将结果保存在 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 文件中链接到程序集的几行:
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”的不兼容重新定义。
编码是我的弱点。任何帮助或指示将不胜感激!
解决方案
通常,特定目标的特定编译器版本使用的调用约定特定于该编译器和版本。并且技术上随时可能发生变化(即使我们已经看到了 gnu 和 arm),并且没有理由期望任何其他编译器符合相同的约定。尽管像 gcc 和 clang 这样的编译器符合 arm 推荐的 abi 的某个版本,但随着时间的推移,abi 已经发生了变化,而 gcc 也随之发生了变化。
As Peter pointed out:
LDR R1, =OPERAND_1; loads R1 with OPERAND_1
(you are clearly not using gnu assembler, so not the gnu toolchain correct? probably Kiel or ARM?)
puts the address of that label into r1 to get the contents you need another load
ldr r1,[r1]
and now the contents are there.
Using global variables gets you around the calling convention problem.
Using a simple example and disassembling you can discover the calling convention for your compiler:
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)
first parameter in r0, second in r1, return in r0. which could technically change on any version of gnu going forward but can tell you from gcc 2.x.x to the present 9.1.0 this is how it has been for arm. gcc 3.x.x to the present for thumb which is what you are using.
How you have done it is fine, you just need to recognize what the =LABEL shortcut thing really does.
推荐阅读
- enterprise-architect - Sparx EA VBScript。如何“someInformationFlow.ConveyedItems.AddNew”?
- winforms - 配对 BLE 设备
- string - POSIX sh:如何仅使用 shell 将整个文件读入单个字符串,同时在原始文件中保留空格和换行符?
- javascript - 从颜色选择器 Three.js 中选择颜色
- git - 如何从 .gitignore 子文件夹中排除所有扩展名(但不包括 PHP 和 JS)?
- php - PHP 如何在 csv 文件中打印数组?
- mariadb - MariaDB 生成列 vs. 内置函数,哪个更快?
- elasticsearch - 估计弹性搜索索引大小的最佳方法
- c# - 如何从实体框架数据库中获取包含在类中的项目列表
- php - 如果不使用 mysqli_multi_query,SQL 注入将无法工作