stm32在keil IDE中,默认使用的是armcc编译器,因此下面的语法,都是针对该编译器而言的,如果是针对gnu gcc编译器,有些不同,可以看我之前这两篇文章:
https://biao2488890051.blog.csdn.net/article/details/118518236
GCC内嵌汇编与C语言相互调用(一文读懂)_biao2488890051的博客-CSDN博客_arm c内嵌汇编
内联汇编
这是在c语言函数内部嵌入一段汇编指令,但是里面用到的寄存器必须先以变量形式声明,但是官方文档又说了,这个名字和物理寄存器不一定对应的,除非以register形式声明。对于核心寄存器,必须以全局变量形式声明,非核心的可以以局部变量声明(但是不知道为什么我这样弄也不行),这样内嵌汇编操作的就是物理寄存器了。但是全局变量声明的寄存器可能没法用于其它编译处理了,哎,真是难用,官方文档链接Compiler User Guide: Inline assembler rules for compiler keywords __asm and asm
register unsigned int reg_r6 __asm("r6");
void NE_HandlerBp(void)
{
int a;
__asm
{
mov reg_r6, 5
sub reg_r6, reg_r6, 4
}
a = 2;
}
上面方法对于操作一般寄存器还是好用方便的,但是操作lr,pc等寄存器,就直接不行了,反汇编这几条汇编竟然对应的是nop指令,应该是因为这些敏感寄存器一旦被设为全局寄存器变量,就不能被编译器用于其它编译了吧。
嵌入汇编
指在C文件中,以c语言形式定义一个汇编函数,别的函数调用该函数时候,还是会自动压栈什么的,但是在这个汇编函数内部,就需要我们自己保存一些用到的寄存器了,如下:
__asm int My_add(int a, int b)
{
ADDS R0, R0, R1
BL __cpp(fun1)
LDR R0, __cpp(&a)
BX LR
}
内在函数
这些函数由编译器内部定义或者CMSIS-Core定义的,这些是一些特定的指令啥的,就是c语言不好直接实现的,例如,前导码计算指令 CLZ,就默认被定义为了一个内在函数
unsigned char __clz(unsigned in val)
总结
armcc支持的这些方面没有gcc的好用,特别是内联汇编,可以看出,很容易出问题,不建议用,我看了core_cm3.c文件,也就是内核文件,里面用的都是内嵌汇编,没用内联汇编,说明真的不好用。