Cortex-M系列:在C文件中插入汇编

本文旨在阐述如何在Cortex-M系列CPU的C文件中插入汇编程序。通过观察C语言生成的汇编程序,在必要时刻知道如何写更为复杂的汇编代码。通过学习ARM工具链生成的汇编程序,可实现较高效的汇编指令学习,更重要的在于知道程序有多大的优化空间。特别地,理解数组处理方式,能更深刻地理解数组越界到底会有怎样的影响;理解文本池访问的方式,能更直观地知道常量以及const关键字在汇编中是如何体现的。

本文承接参考链接[3]和[7],故对一些概念没有再具体讲解。

目录

1 Cortex-M7程序生成

1.1 基本概念

1.2 书写规范[6]

1.3 嵌入汇编

1.4 内联汇编

1.5 其他汇编形式

2 C函数例子——基本运算

2.1 加法测试

2.2 乘除减和移位

2.3 浮点测试

2.4 数组处理,SP相关寻址

2.5 多参数调用

2.6 排他访问

2.7文本池访问

3 参考资料


1 Cortex-M7程序生成

编译的整个过程为:预编译、编译、汇编、链接

1.1 基本概念

格式:

[标号] <指令|条件|S> <操作数>;[注释]

注:指令指伪指令或汇编指令;条件和S见“表5.3 Cortex-M 汇编语言的后缀”[1]。

1、在ARM工具链和GNU工具链的伪指令是不同的,即不同的编译器GNU的伪指令可能不同。一般GNU工具链的伪指令以“.”为开头。下面我将在Keil5中使用ARM工具链测试一些汇编指令,都是在.c文件中编写和调用。

2、汇编指令到具体CPU手册找,如[2]

2、操作数可以是下表的寄存器,也可以是立即数“#0x01”,或是定义的常量(在ARM工具链中,用“EQU”定义,用“=常量名”引用),或是指针的本质用法("[R3]")。

寄存器

__asm中的字符串

APSR

"apsr"

BASEPRI

"basepri"

BASEPRI_MAX

"basepri_max"

CONTROL

"control"

EAPSR(EPSR+APSR)

"eapsr"

EPSR

"epsr"

FAULTMASK

"faultmask"

IAPSR(IPSR+APSR)

"iapsr"

IEPSSR(IPSR+EPSR)

"iepsr"

IPSR

"ipsr"

MSP

"msp"

PRIMASK

"primask"

PSP

"psp"

PSR

"psr"

 r0~r12

"r0"~"r12"

 r13

"r13"或“sp”

 r14

"r14"或"lr"

 r15

"r15"或“oc”

XPSR

"xpsr"

1.2 书写规范[6]

a\所有标号必须在一行的顶格书写

b\所有的指令均不能顶格书写

c\标识符大小写敏感

d\ARM指令、伪指令、寄存器名可以全部大写字母,也可以全部小写字母,但不要大小写混合使用。

(如可以"BX lr”,但不能“Bx lr”)

e\语句间可以插入空行,也可以某行只有标号,以使得源代码的可读性更好。

1.3 嵌入汇编

__asm uint8_t myADD( uint8_t lhs,uint8_t rhs )
{
	MOV r2,r0
	ADDS r0,r2,r1
	UXTB r0,r0
	BX lr
}

注:容易出现“表面语法错误”,编译后并不会报错。

嵌入汇编提供一个汇编函数的空壳子,提供个入口,里面的所有操作都有程序员自己写,尤其是lhs和rhs不能在汇编中直接使用。在调用者调用时,lhs存在r0,rhs存在r1[7]。需要返回的值应该写在r0上。函数的返回也需要将LR写入CP寄存器来返回。中间的过程再补充一下就行。

调用者使用的C语言及发生的汇编如下:

remp = testAdd(10,20);

想要在汇编中直接使用lhs和rhs可用下一方法。

1.4 内联汇编

内联汇编的框架有C函数搭建,在内联汇编里即可以使用寄存器名,也可以使用“可见”的C变量。

uint8_t myADD1( uint8_t lhs,uint8_t rhs)
{
	uint8_t rslt;
	__asm
	{
		ADD rslt,lhs,rhs
	}
	return rslt;
}

uint8_t myADD2( uint8_t lhs,uint8_t rhs)
{
	uint8_t rslt;
	__asm("ADDS rslt,lhs,rhs");
	return rslt;
}

两个函数的汇编结果相同,结果如下所示:

Cortex-M系列:在C文件中插入汇编_第1张图片

 

1.5 其他汇编形式

从汇编中调用C函数

IMPORT my_add_c

BL my_add_c

从C程序中的汇编代码

BL _cpp(my_add_c)

从C中调用汇编函数

EXPORT My_Add

注:详见[1]中的第20章

2 C函数例子——基本运算

记得将优化等级改为最低。下面的代码可能有的复制不完整,特性是BX指令。

2.1 加法测试

 uint64_t和int64_t没有在本文测试。

Cortex-M系列:在C文件中插入汇编_第2张图片

Cortex-M系列:在C文件中插入汇编_第3张图片

2.2 乘除减和移位

Void BHWTest2(void)

 

Cortex-M系列:在C文件中插入汇编_第4张图片

Void S_BHWTest2(void)

 

Cortex-M系列:在C文件中插入汇编_第5张图片

2.3 浮点测试

Cortex-M系列:在C文件中插入汇编_第6张图片

注意这里是用BX返回调用者的。

2.4 数组处理,SP相关寻址

Cortex-M系列:在C文件中插入汇编_第7张图片

a、为了在(向下增长的)栈中给数组留下空间,程序直接移动了栈指针。这个技术成为“SP相关寻址”

b、因为程序调用了子函数,因此使用“PUSH {lr}”和“POP {pc}”组合更高效。

c、调用ARM的标准库函数时,可以发现函数只把memset函数的第一个参数和第三个参数传入了,可能是它内部优化导致的吧。

2.5 多参数调用

调用者部分:

Cortex-M系列:在C文件中插入汇编_第8张图片

被调用者部分:

Cortex-M系列:在C文件中插入汇编_第9张图片

a\压入栈的有4个寄存器,每个寄存器4字节,于是栈地址减小了0x10.

b\比较特别的是,调用者知道多余的参数会“破坏”栈,所以提前把R3这个非被调用者保存寄存器保存起来,供第5个参数破坏。

c\显然这个函数效率很低,如果用SIMD中的UADD8,那速率就快多了。这也是汇编加速可操作的地方吧。但不确定3级或2级优化下,这里是否优化,感兴趣的读者可以自己试一下。

2.6 排他访问

自己还没试过,主要是没需求,另外就是[9] 基于ARM的排他访问原理及应用 写的太好了。

2.7文本池访问

实例1:当非零组数定义在函数内

Cortex-M系列:在C文件中插入汇编_第10张图片

由于里面有数组,所有使用了4.4节的相关寻址的概念,但不是这节的重点。值得一提的是,虽然数组的有效数只有0x4C的大小,sizeof(BASEtable2)==0x4C,但在数组前留了4个字节,或者说多压了4个字节入栈。

1、由于这里的数组时非零数组,于是隐式调用了memcpy(r0,r1,r2)函数。

2、而原始数据存储的地方是在代码段,定义局部数组,所有需要把代码段内的值赋值到栈中。

3、当真正运行到0x08005EEE行时,PC指针的值其实是0x08005EF0 ,即该行指令的下一个指令的地址(这一点需要特别注意)。

0x08005EF0+24=0x08005F08

这个地址正好是函数结束后的内存(考虑4字节对齐),没错这个就是0x081075C8,

Cortex-M系列:在C文件中插入汇编_第11张图片

实例2:当常量非零数组定义在函数外,

Cortex-M系列:在C文件中插入汇编_第12张图片

和实例1比,少了隐含数组复制。

实例3:单个常量

Cortex-M系列:在C文件中插入汇编_第13张图片

有意思,常量不是在Flash中的真常量,而是一个常变量,使用强制转换功能是改用改变这个“常变量”的值的。

3 参考资料

[1] Joseph Yiu. ARM Cortex-M3与Cortex-m4权威指南(第3版)[M]. 吴常玉,曹孟娟,王丽红,译. 北京:清华大学出版社,2015.

[2] ARM® Cortex®-M7 Devices Generic User Guide

[3]Cortex-M系列:ARM架构与汇编指令集 https://blog.csdn.net/NoDistanceY/article/details/104177163

[6] Thumb指令集及汇编格式 https://wenku.baidu.com/view/49ab91606fdb6f1aff00bed5b9f3f90f77c64d5a.html

[7] Cortex-M系列:非中断、特权模式下的汇编语言 https://blog.csdn.net/NoDistanceY/article/details/104003831

[8] Cortex-M for Beginners - 2017_EN_v2  https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/white-paper-cortex-m-for-beginners-an-overview-of-the-arm-cortex-m-processor-family-and-comparison

[9] 基于ARM的排他访问原理及应用 https://blog.csdn.net/tissar/article/details/83008719

 

你可能感兴趣的:(嵌入式,Thumb汇编,const,SP相关寻址,排他访问)