C和C++编译器中内置了内嵌汇编器,可以用其实现C语言不能或不易完成的操作。
1.内嵌汇编指令的用法
内嵌汇编指令支持大部分ARM和Thumb指令,其在使用上有以下特点。
1)操作数
内嵌汇编指令的操作数可以是C或C++表达式,这些表达式的值均按无符号数处理。当指令中同时使用寄存器和C或C++表达式时,表达式不要过于复杂,以免编译器在计算表达式时用到过多的寄存器以致与指令中所用的寄存器冲突。
2)寄存器
一般不存推荐直接使用寄存器,因为可能影响编译器的寄存器分配,从而影响程序效率。如果必须使用要注意:不要向PC赋值,只能利用B或BL指令实现跳转;需要注意编译器可能会使用寄存器r12和r13存储临时变量,在计算表达式的值时可能会把寄存器r0~r3、r12、r14用于函数调用;如果C语言变量用到了指令中用到的物理寄存器,编译器一般会在必要时用栈保存或恢复这些寄存器,但排除SP、SL、FP和SB。
3)常量
定值表达式前的“#”可以省略,如果用“#”,则其后面必须是常量。
4)标号
可以利用B指令(不能用BL指令)跳转到C或C++语言中的标号。
5)指令展开
除了与协处理器相关的指令,大多数ARM或Thumb指令对常量的操作会被展开成多条指令,各指令的展开对条件标志位的影响情况为:算术指令可以正确地设置N、Z、C、V条件标志位;逻辑指令可以正确地设置N、Z条件标志位,不影响V条件标志位,破坏C条件标志位。
6)内存分配
所有的内存分配在C或C++语言程序中声明,通过标号在内嵌汇编中引用,不要在内嵌汇编中用伪操作分配内存。
7)SWI和BL指令的使用
在内嵌汇编的SWI和BL指令中,除了正常的操作数域外,还必须增加如下3个可选的寄存列表:第1个寄存器列表中的寄存器用于存放输入的参数;第2个寄存器列表中的寄存器用于存放返回的结果;第3个寄存器列表中的寄存器的内容可能被调用的子程序破坏。
2.内嵌汇编器与ARM ASM汇编器的区别
使用内嵌汇编应注意以下几点:(www.xing528.com)
(1)不能通过(.)或{PC}获得当前指令地址。
(2)不能用“LDR Rn,=expr”伪指令,可以用“MOV Rn,expr”替代(可生成从数据缓冲池中加载数据的汇编指令)。
(3)不支持标号表达式。
(4)不支持ADR和ADRL伪指令。
(5)表示十六进制数只能用0x,不能用&。
(6)编译器可能使用寄存器r0~r3、IP及LR存放中间结果,因此在使用这些寄存器时要注意。
(7)CPSR中的N、Z、C、V条件标志位可能会被编译器在计算C语言表达式时改变,因此在指令中使用这些条件标志位时要注意。
(8)指令中使用的C语言变量不要与ARM物理寄存器同名。
(9)LDM与STM指令的寄存器列表中只能使用物理寄存器,不能使用C语言表达式。
(10)不能写寄存器PC,不支持BX和BLX指令。
(11)用户不需要维护数据栈,因为编译器会根据需要自动保存或恢复工作寄存器的值。
(12)用户可以改变处理器模式,修改ATPCS寄存器SB、SL、FP,改变协处理器的状态,但这并不为编译器所知。所以,如果用户改变了处理器的模式,则不要使用原来的C语言表达式,直至重新恢复到原来的处理器模式后,方可使用这些C语言表达式。
3.内嵌汇编在C和C++语言程序中的使用格式
在标准C语言中可以使用__asm关键字声明内嵌汇编语句,格式如下:
其中,如果一条指令占多行,用“\”续行;一行多条指令用“;”分隔,不能用“;”注释,可用C语言的注释方法。
在C++语言中,除了以上方法外还可用asm关键字,格式如下:
其中,括号内必须是一个指令序列的字符串。
示例代码如下:
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。