c语言程序main.c
#include<stdio.h> extern void Init_1(void); int main() { Init_1(); return 0; }
汇编程序Func.s
AREA My_Function,CODE,READONLY ;这一行必有的除了My_Function可以自己取名以外,其他都是模板 EXPORT Init_1 ;与在C文件中定义的Init_1函数关联起来 ;高级语言中的声明和使用变量其实是对寄存器的使用,所以我们只需要直接使用寄存器即可 Init_1 MOV R1,#0 ;设R1寄存器是i MOV R2,#0 ;设R2寄存器是j LOOP ;写在最左边的是程序段的段名,执行跳转程序时要用到 CMP R1,#10 ;比较R1和10的大小 BHS LOOP_END ;如果R1大于或等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句 ADD R2,#1 ;j++ ADD R1,#1 ;i++ B LOOP ;执行一次循环后,无条件再次进入循环判断,即是跳转到LOOP段 LOOP_END NOP END ;必须空格后再写END,不然会被认为是段名,表示程序结束
我们在keil中进行仿真调试,具体如何在keil中创建工程以及如何软件仿真可以参考我以前的文章
断点调试
若我们在MOV R1,#0处设置断点,会发现左上角R1、R2的值都没变,为0
重新设置断点后,每RUN一次,R1、R2都会+1,直至为10跳出循环
我们将上面的Func.s修改一下,使原汇编语言 Init_1函数的类型改为 int Init_1(init) ,此函数功能修改为 传入一个整型数x,函数运行后返回整型数 x+100。
修改后的Func.s
AREA My_Function,CODE,READONLY EXPORT Init_1 Init_1 ADD R6,#100 MOV PC,LR END
main.c
#include<stdio.h> extern int Init_1(int); int main() { Init_1(3); return 0; }
编译并调试后,能够看到R6的值发生了改变
我们仍然在前面代码的基础做修改,下面是修改后的代码
main.c
#include<stdio.h> extern int Init_1(int x); int re(void); int main() { int x = Init_1(420); printf("%d",x); return 0; } int re(void) { return 5; }
Func.s
AREA My_Function,CODE,READONLY ;这一行必有的 除了My_Function可以自己取名以外,其他都是模板 EXPORT Init_1 ;与在C文件中定义的Init_1函数关联起来 IMPORT re ;声明return1为外部引用 ;高级语言中的声明和使用变量其实是对寄存器的使用,所以我们只需要直接使用寄存器即可 Init_1 ADD R0,#100 ;将传入的值+100 MOV PC,LR ;返回R0 LOOP ;写在最左边的是程序段的段名,执行跳转程序时要用到 CMP R1,#10 ;比较R1和10的大小 BHS LOOP_END ;如果R1大于或等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句 ADD R2,#1 ;j++ ADD R1,#1 ;i++ B LOOP ;执行一次循环后,无条件再次进入循环判断,即是跳转到LOOP段 LOOP_END NOP END ;必须空格后再写END,不然会被认为是段名,表示程序结束
编译调试
可以看到R0变成了5,c函数调用成功
在汇编程序中调用c语言其实还可以使用BL+函数名称;汇编函数传入参数需要选择对应的寄存器,因为传递的参数数量有限,不同参数类型对应的寄存器也不同。
用51汇编完整写一个函数
浅谈C语言与汇编语言混合编程