(十)C和汇编混合编程

本专栏总结王利涛《C语言嵌入式Linux高级编程》第二期课程

一、ATPCS规则

  • ATPCS: ARM-Thumb Procedure Call Standard
  • 堆栈使用规则
    • 使用满递减堆栈,入栈出栈操作使用LDMFD/STMFD
  • 子程序调用基本规则
    • ①子程序间通过寄存器R0-R3 传递参数和返回结果,参数多于4个,其余的使用堆栈传参。
    • ②子程序中使用R4-R11保存局部变量。
    • ③R12作为过程调用中的临时寄存器,用于保存SP,记作IP。
    • ④R13作为数据栈指针,记作SP。
    • ⑤R15作为程序计数器,记作PC。

二、ARM编译器内嵌汇编

  • 关键字 __asm

  • ARM 编译器对ANSI C进行扩展,使用__asm在C语言中内嵌汇编
    __asm
    {
    指令

    }

  • 实例

int src[10] = {1,2,3,4,5,6,7,8,9,10};
int dst[10] = {0};
int i = 0;

int main(void)
{
	for (i = 0; i < 10; i++)
		dst[i] = src[i];
	return 0;
}

----------------------------------------------
内嵌汇编方式(只能适用于ARM的编译器)
int main(void)
{
	__asm
	{
		ldr r0,=src
		ldr r1,=dst
		mov r2,#10
	loop:
		ldr r3,[r0],#4
		str r3,[r1],#4
		subs r2,r2,31
		bne loop
	}
	return 0;
}

三、GNU内嵌汇编

  • 关键字 __asm__
  • GNU编译器对ANSI C 进行扩展,使用__asm__ 修饰,表示后面的代码为内嵌汇编,其后可选择使用 __volatile__ 告诉编译器不要优化代码:
__asm__ __volatile__
{
	汇编语句;
	...
}
  • 内嵌单行汇编代码示例
    asm(“mov r0, r0”);
  • 内嵌多行汇编代码示例
__asm__ __volatile__
{
	"ldr r0,=src;"
	"ldr r1,=dst;"
	"mov r2,#10;"
"loop:"
	"ldr r3,[r0],#4;"
	"str r3,[r1],#4"
	"subs r2,r2,#1"
	"bne loop;"
};

四、汇编中调用C子程序

  • 使用方法
    • 根据ATPCS参数规则,完成参数传递。
    • 满足C语言能够参数残敌和保存局部变量的堆栈环境。
    • 使用BL func 即可(带链接的跳转)
int sum(int a, int b)
{
	int result = 0;
	printf("result = %d\n",result);
	return result;
}
int main(void)
{
	SUM_ASM();  //在C中调用汇编函数
	return 0;
}

-------------------------------------------
IMPORT sum;  先引入要调用函数
AREA SUM_ASM, CODE, READONLY
	EXPORT SUM_ASM
SUM_ASM
	MOV R0,0x03;	传参,传入的参数少于4,用R0-R3
	MOV R1,0x04;
	BL  sum	;		调用C语言函数,跳转之前,保存下一条指令到LR里,执行完sum后,就调回来,sum翻译成汇编包含了这条语句:MOV PC,LR.所以才能返回来。
	MOV PC, LR;		返回到main函数
	END
  • 大于4个参数的函数调用,采用压栈方式
IMPORT sum;  先引入要调用函数
AREA SUM_ASM, CODE, READONLY
	EXPORT SUM_ASM
SUM_ASM
	MOV R0,0x00;	传入参数 0,即a=0
	MOV R1,0x01;	传入参数 1,即b=1
	MOV R2,0X02; 	传入参数 2,即c=2
	MOV R3,0X03;	传入参数 3,即d=3

	MOV R4,0X05	;   传入参数 5,即e=0
	STR R4,[SP,#-4]; 压栈操作,把R4压入栈中,用R4来搬运
	MOV R4,0X04	;	传入参数 4,即f=0
	STR R4,[SP,#-4];
	BL  sum	;		;最后,调用sum函数,同时将参数也传进去
	MOV PC, LR;		返回到main函数
	END

sum的c语言接口:
int sum(int a, int b, int c, int d, int e, int f);

猜你喜欢

转载自blog.csdn.net/weixin_38956024/article/details/107484216
今日推荐