c语言和汇编语言的混合编写

文章目录

一、c语言中调用汇编程序

1. 无参调用

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

c语言和汇编语言的混合编写

重新设置断点后,每RUN一次,R1、R2都会+1,直至为10跳出循环

c语言和汇编语言的混合编写

2. 有参调用

我们将上面的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的值发生了改变

c语言和汇编语言的混合编写

二、汇编中调用c语言

我们仍然在前面代码的基础做修改,下面是修改后的代码

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,不然会被认为是段名,表示程序结束

编译调试

c语言和汇编语言的混合编写

可以看到R0变成了5,c函数调用成功

三、总结

在汇编程序中调用c语言其实还可以使用BL+函数名称;汇编函数传入参数需要选择对应的寄存器,因为传递的参数数量有限,不同参数类型对应的寄存器也不同。

四、参考文献

用51汇编完整写一个函数
浅谈C语言与汇编语言混合编程

上一篇:STM32下C语言与汇编语言混合编程


下一篇:Event Loop