ARM32汇编语言之汇编和C语言交互

952 阅读3分钟

「这是我参与11月更文挑战的第30天,活动详情查看:2021最后一次更文挑战」。

汇编语言和C语言交互

  • 内嵌汇编
  • 外链汇编

1.引入其他源文件函数

使用import或者extern伪指令

;使用import伪指令
AREA code, CODE
import fun1 ;导入其他源文件中名为fun1的函数
END

;使用extern伪指令
AREA code, CODE
extern fun1       
END

两者区别:

  • import:不管当前文件是否使用该引入的函数,该标签都会加入当前文件符号表,即为静态引用
  • extern:只有当前文件使用了该函数,才会将此标签加入符号表,即为动态引用

2.导出当前源文件中函数供其他文件访问

使用export或者global伪指令

;使用import伪指令
AREA code, CODE
export fun         ;导出fun函数供其他源文件使用

fun 
	mov R0,#4
	bx lr
END

3.外链汇编之C语言调汇编函数

第一步,在汇编原文件中将函数暴露出来给供外部调用,使用export或者global伪指令:

AREA code, CODE
export arm_strcpy  ;或者使用global

arm_strcpy
loop 
	ldrb R4,[R0],#1 ;如果使用ldr 那么将偏移值改成4
	cmp R4,#0
	beq over
	strb R4,[R1],#1
	b loop
over	
END

第二步,在C文件中引用汇编中的函数,C文件中只能使用extern伪指令:

extern arm_strcpy(char *src,char*des);

int main2(){
	char *a="hello pangshu";
	char b[64];
	arm_strcpy(a,b);
}

4.外链汇编之汇编调c语言函数

第一步,在C文件中编写好函数

int c_sum(int a,int b){
	return a+b;
}

第二步, 在汇编文件中引入函数,使用import或者extern伪指令

AREA code, CODE
import c_sum  

mov R0,#1 ;第一个参数
mov R1,#2 ;第二个参数

END

第三步, 使用BL指令调用函数

AREA code, CODE
import c_sum  

mov R0,#1 ;第一个参数
mov R1,#2 ;第二个参数
BL c_sum
END

在ARM中函数参数使用R0~R3这四个寄存器来进行传递,最多传递4个参数,超过4个参数使用栈进行处理,函数返回值通过R0进行传递

由于keil软件的特殊性,我们可以通过以下方式进行互调测试

C文件中代码:

#include<stdio.h>
extern arm_strcpy(char *src,char*des);

int main2(){
	
	char *a="hello pangshu"	;
	
	char b[64];

	arm_strcpy(a,b); //调汇编中函数
	return 0;
}

int c_sum(int a,int b){
	return a+b;
}

汇编文件中代码:

 AREA code, CODE

 import c_sum   
 export arm_strcpy  

arm_strcpy

	mov R0,#1 ;第一个参数
	mov R1,#2 ;第二个参数
	BL c_sum  ;结果存放至R0中
	END

5.内嵌汇编

在C语言中嵌入汇编代码,格式如下:

int main2(){
    int a=4;
    int b=4;
    int c=4;
  
	__asm__{         //使用__asm或者__asm__
	mov R5,#0x00000005   //在大括号内部直接写入汇编代码即可
	mov R6,#0x00000005
	}
	return 0;
}

内嵌汇编的注意事项:

  • 不能直接给PC寄存器赋值,如果想改变pc值需要借助转移指令
  • 由于R0 ~ R3用于存放函数参数和返回值,R12 ~ R15有特殊用途,因此我们能操作的寄存器只有R4~R11, 又因为编译器会优先将寄存器分配给函数中的局部变量,因此我们一般无法在内嵌汇编环境中准确地修改某个寄存器的值,比如我想修改R5寄存器的值,由于函数有个变量占用了R5这个寄存器,那么编译器会自动将你写的这个R5改成R6或者其他,所以,在内嵌汇编时我们需要把寄存器当作变量来看待,把局部变量也当成寄存器看待,就好理解了
void c_strcopy(char *src,char *des){
	char ch
	__asm__{    
    loop:
    	ldrb ch,[src],#1  //局部变量当成寄存器看待
    	strb ch,[des],#1
    	cmp,ch,#0
    	bne loop
	}
	
}