D10. 伪操作与混合编程-ARM体系结构与接口技术-嵌入式学习LV9

DAY10. 伪操作与混合编程


如果出现图片无法查看可能是网络问题,我用的GitHub+图床保存的图片,可以参考我另外一篇文章GitHub的使用方法含网络问题解决
GitHub使用教程含网络问题_github加速器_肉丸子QAQ的博客-CSDN博客


1. 伪操作

GNU的伪操作一般都以.

.global

	 .global symbol
	@ 将symbol声明成全局符
  • 当一个项目需要多个.s文件时,没有声明全局符是无法调用的

.local

	 .local symbol
	@ 将symbol声明成局部符号,只能在当前.s文件使用	

.equ

	 .equ DATA, 0xFF @类似于C语言的宏定义
	 MOV R1, #DATA

通过反编译可以看出MOV指令占用的是0地址,说明.equ是不会生成指令的


.macro

将语句封装

	 @ 封装开始
	 .macro FUNC
		MOV R1, #1
		MOV R2, #2
	 .endm
	 @封装结束
	 FUNC

将程序复位后可以看到指针指向FUNC

条件编译.if .endif

	 .if 0 @1会编译机器码,0不编译
		MOV R1, #1
		MOV R2, #2
	 .endif

程序复位后指针直接指向了B


.rept

	.rept 3 @重复编译的次数
	 	MOV R1, #1
	 	MOV R2, #2
	.endr

D10. 伪操作与混合编程-ARM体系结构与接口技术-嵌入式学习LV9_第1张图片

可以看到编译了3次指令出来

.weak

弱化一个符号,即告诉编译器即便没有这个符号也不要报错

	@ .weak symbol
	@ 弱化一个符号,即告诉编译器即便没有这个符号也不要报错
	 .weak func
	 B func

D10. 伪操作与混合编程-ARM体系结构与接口技术-嵌入式学习LV9_第2张图片

.word

在当前地址申请一个字的空间并将其初始化为VALUE

	@ .word VALUE
	@ 在当前地址申请一个字的空间并将其初始化为VALUE
	 MOV R1, #1
	 .word 0xFFFFFFFF
	 MOV R2, #2

可以看到04的地址被占用掉了,只是用来放的数据

.byte

在当前地址申请一个字节的空间并将其初始化为VALUE

	@ .byte VALUE	
	@ 在当前地址申请一个字节的空间并将其初始化为VALUE
	 MOV R1, #1
	 .byte 0xFF
	 MOV R2, #2
  • 因为指令都是4的整数倍,当使用.byte后会占用04的地址,第二条MOV指令会从05开始不满足条件无法编译成功

将5-7的地址空出来,从08开始就能解决这个问题

  • 如何空出地址需要用到另外一个伪操作.align

.align

告诉编译器后续的代码2的N次方对齐

	@ .byte VALUE	
	@ 在当前地址申请一个字节的空间并将其初始化为VALUE
	 MOV R1, #1
	 .byte 0xFF
	
	@ .align N
	@ 告诉编译器后续的代码2的N次方对其
	 .align 4
	 MOV R2, #2

当N取4时就是16,可以看到第二条MOV指令存放在16(16进制就是10)的位置

.arm

告诉编译器后续的代码是ARM指令

	@ .arm
	@ 告诉编译器后续的代码是ARM指令

.thumb

告诉编译器后续的代码是Thumb指令

@ .thumb
@ 告诉编译器后续的代码是Thumb指令


.text

定义一个代码段

@ .text				
@ 定义一个代码段

.data

定义一个数据段

@ .data				
@ 定义一个数据段

.space

在当前地址申请N个字节的空间并将其初始化为VALUE

@ .space N, VALUE
@ 在当前地址申请N个字节的空间并将其初始化为VALUE
 MOV R1, #1
 .space 12, 0x12
 MOV R2, #2

D10. 伪操作与混合编程-ARM体系结构与接口技术-嵌入式学习LV9_第3张图片

不同的编译器伪操作的语法不同

2. C与汇编的混合编程

  • 数据处理指令、跳转指令、内存访问指令是CPU的通用指令,在ARM中能用,在其他也能用
  • MSR状态寄存器传送指令、SWI指令、协处理器指令,ARM专用指令,其他CPU不一定能用

C和汇编的混合编程原则

在哪种语言环境下符合哪种语言的语法规则:

  1. 在汇编中将C中的函数当做标号处理:汇编没有函数的概念,调用C语言就要去掉括号

  2. 在C中将汇编中的标号当做函数处理:C语言的函数后面是有括号的,调用汇编的话就需要补上

  3. 在C中内联的汇编当做C的语句来处理

两种混合编程方式

  • 方式一:汇编语言调用(跳转)C语言

.s文件

 		 MOV R1, #1
		 MOV R2, #2
		 BL  func_c
		 MOV R3, #3

.c文件

void func_c(void)
{
	int a;
	a ++;
	a --;
}
  1. 通过调试我们可以发现当执行到BL后LR会保存下一条的地址
  1. 当执行完C语言后跳转BL的后一条指令
  1. 要想从C语言跳转回来的话就需要将LR值给PC,所以C语言最后一句话会自己写一条指令
  • 方式二:C语言调用(跳转)汇编语言

.c文件

void func_c(void)
{
	int a;
	a ++;
	FUNC_ASM();
	a --;
}

.s文件

		 MOV R1, #1
		 MOV R2, #2
		 BL  func_c
		 MOV R3, #3
		

 .global FUNC_ASM @使用伪操作声明全局符
 FUNC_ASM:
		 MOV R4, #4
		 MOV R5, #5

当C语言结束后跳转到相应的汇编代码位置

以上两种都是需要创建.s .c文件,通过两个文件之间的跳转来实现混合编程

  • C内联(内嵌)汇编

    在C语言中插入汇编

    void func_c(void)
    {
    	int a;
    	a ++;
    	//C内联(内嵌)汇编
    	asm
    	(
    		"MOV R6, #6\n"
    		"MOV R7, #7\n"
    	);
    	//C语言调用(跳转)汇编语言
    	FUNC_ASM();
    	a --;
    }
    
    

3. ATPCS协议

ATPCS协议:(ARM-THUMB Procedure Call Standard)

ATPCS协议主要内容

  1. 栈的种类

    1. 使用满减栈
  2. 寄存器的使用

    1. R15用作程序计数器,只能用于储存程序的指针,不能作其他用途
    2. R14用作链接寄存器,只能用于存储返回地址,不能作其他用途
    3. R13用作栈指针,只能用于存储栈指针不能作其他用途
    4. 当函数的参数不多于4个时使用R0-R3传递,当函数的参数多于4个时,多出的部分用栈传递
    1. 函数的返回值使用R0传递
    1. 其它寄存器主要用于存储局部变量
int a=1,b=1,c=1,d=1,e=1,f=1,g;

int func(int a,int b,int c,int d,int e,int f)
{
	return a+b+c+d+e+f;
}

int main(void)
{
	g = func(a,b,c,d,e,f);
	return 0;
}

4. 作业

1.简述ATPCS协议的主要内容是什么

   		 1.栈的种类
   		 	1.1 使用满减栈
   	
   		 2.寄存器的使用
   			2.1 R15用作程序计数器,不能作其他用途	
   		 	2.2 R14用作链接寄存器,不能作其他用途
   			2.3 R13用作栈指针,不能作其他用途
   			2.4 当函数的参数不多于4个时使用R0-R3传递,当函数的参数多于4个时,多出的部分用栈传递
   			2.5	函数的返回值使用R0传递
   		 	2.6 其它寄存器主要用于存储局部变量

你可能感兴趣的:(arm开发,学习,linux,驱动开发)