目录
一、在C程序中调用汇编程序
新建一个工程,这里我选择的芯片是STM32F103RC,配置如下:
接着创建一个main.c文件
程序代码如下:
#include<stdio.h>
extern void Init_1();
int main(){
Init_1();
return 0;
}
然后再建立一个汇编文件,func.s
程序代码如下:
AREA My_Function,CODE,READONLY
EXPORT Init_1
Init_1
MOV R1,#0
MOV R2,#0
LOOP
CMP R1,#10
BHS LOOP_END
ADD R2,#1
ADD R1,#1
B LOOP
LOOP_END
NOP
END
注:其中EXPORT是将C文件里的相关函数进行调用
MOV R1,#0 MOV R2,#0 是将寄存器R1和R2赋值为0
CMP R1,#10 BHS LOOP_END 是将寄存器R1与10进行比较,如果R1>10,就转到LOOP_END
ADD R2,#1 ADD R1,#1 是将寄存器R2和R1自增1
B LOOP 是代表再次进入循环
END 是表示结束程序
由于本次的实验需要用到仿真调试,所以我要点击魔法棒中的Debug,将其中设置为如下图所示:
配置好后,我们点击debug开始调试
点击单步调试Step,观察寄存器R1和R2里面值的变化
我们可以看到寄存器里的R1和R2从0依次递增到了A(即为10),然后跳出循环,结束程序
二、修改汇编语言
修改上面的代码,将原汇编语言 Init_1函数的类型改为 int Init_1(int) ,修改后的函数功能为传入一个整型数x,函数运行后返回整型数 x+100。
修改main.c为:
# include<stdio.h>
extern int Init_1(int x);
int main(){
int m = Init_1(10);
printf("%d", m);
return 0;
}
修改func.s为:
AREA MY_Function,CODE,READONLY
EXPORT Init_1
Init_1
ADD R0,#100 ;将传入的值加100
MOV PC,LR ;返回R0
LOOP
CMP R1,#10
BHS LOOP_END
ADD R2,#1
ADD R1,#1
B LOOP
LOOP_END
NOP
END
编译之后,设置断点开始调试
此时Init_1(10)的10被传入R0中
这里可以m的值为0x6E(即10进制下的110)说明调用成功了
三、在汇编程序中调用C程序
接下来在汇编函数中调用一个 C语言写的函数
funs.s
AREA main,CODE,READONLY
import addf
ENTRY
EXPORT __main
__main
mov r0,#10 ;给两个参数赋值
mov r1,#12
bl addf ;调用函数
end
main.c
#include<stdio.h>
int addf(int a,int b){
int result=a+b;
return result;
}
经过仿真调试后,可以看到在这个时候R0和R1已经附上初值10和12
再次点击单步调试,R0里的值就变为之前R0与R1之和,变为16(即十进制下的22)
变量的值我们也可以看见,结果正是我们想要的
四、寄存器使用规则
1. R0-R3 用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 R0-R3 用于任何用途。被调用函数在返回之前不必恢复R0-R3。---如果调用函数需要再次使用 R0-R3 的内容,则它必须保留这些内容。
2. R4-R11 被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。R11 是栈帧指针 fp。
3.R12 是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。
4. 寄存器R13 是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。
5. 寄存器R14 是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将R14 用于其它用途,程序返回时要恢复
6. 寄存器 R15 是程序计数器 pc。它不能用于任何其它用途。
六、参考文献
C语言在ARM中函数调用时,栈是如何变化的? - 云+社区 - 腾讯云为什么会写篇栈变化的文章?做系统分析的话你肯定遇到过一些crash, oops等棘手问题,一般大家都会用 gdb, objdump 或者 addr2line等工...https://cloud.tencent.com/developer/article/1593645STM32的C与汇编语言混合编程_鹤引的博客-CSDN博客STM32的C与汇编语言混合编程混合编程C语言嵌套汇编调用函数操作无参数有参数汇编语言嵌入C语言总结参考混合编程C语言还是有其局限性。有些硬件地址是没有地址一说的。比如处理器的寄存器,协处理器和协处理器的寄存器,系统控制器等。这些硬件资源是不可能使用C语言指针来访问的,这时就只好应用汇编指令了。汇编程序中调用C语言函数汇编程序使用C语言中定义的全局变量、、C语言中使用汇编程序中定义的全局变量C语言中使用汇编程序中定义的全局变量C语言中内嵌汇编指令C语言嵌套汇编调用函数操作无参数C语https://blog.csdn.net/weixin_47554309/article/details/120688906?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163387550216780269847606%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163387550216780269847606&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-5-120688906.pc_search_result_cache&utm_term=STM32%E7%9A%84C%E4%B8%8E%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E6%B7%B7%E5%90%88%E7%BC%96%E7%A8%8B&spm=1018.2226.3001.4187