本文引用地址:http://www.eepw.com.cn/article/257034.htm
内联汇编和嵌入型汇编是包含在C/C++编译器中的汇编器。使用它可以在C/C++程序中实现C/C++语言不能完成的一些工作。例如,在下面几种情况中必须使用内联汇编或嵌入型汇编。
·程序中使用饱和算术运算(Saturatingarithmetic),如SSAT16和USAT16指令。
·程序中需要对协处理器进行操作。
·在C或C++程序中完成对程序状态寄存器的操作。
使用内联汇编编写的程序代码效率也比较高。
12.1.1内联汇编
1.内联汇编语法
内联汇编使用“_asm”(C++)和“asm”(C和C++)关键字声明,语法格式如下所示。
·__asm(instruction[;instruction]); //必须为单条指令
__asm{instruction[;instruction]}
·__asm{
...
instruction
...
}
·asm(instruction[;instruction]); //必须为单条指令
asm{instruction[;instruction]}
·asm{
...
instruction
...
}
内联汇编支持大部分的ARM指令,但不支持带状态转移的跳转指令,如BX和BLX指令,详见ARM相关文档。
由于内联汇编嵌入在C或C++程序中,所有在用法上有其自身的一些特点。
①如果同一行中包含多条指令,则用分号隔开。
②如果一条指令不能在一行中完成,使用反斜杠“/”将其连接。
③内联汇编中的注释语句可以使用C或C++风格的。
④汇编语言中使用逗号“,”作为指令操作数的分隔符,所以如果在C语言中使用逗号必须用圆括号括起来。如,__asm{ADDx,y,(f(),z)}。
⑤内联汇编语言中的寄存器名被编译器视为C或C++语言中的变量,所以内联汇编中出现的寄存器名不一定和同名的物理寄存器相对应。这些寄存器名在使用前必须声明,否则编译器将提示警告信息。
⑥内联汇编中的寄存器(除程序状态寄存器CPSR和SPSR外)在读取前必须先赋值,否则编译器将产生错误信息。下面的例子显示了内联汇编和真正汇编的区别。
错误的内联汇编函数如下所示。
intf(intx)
{
__asm
{
STMFDsp!,{r0} //保存r0不合法,因为在读之前没有对寄存器写操作
ADDr0,x,1
EORx,r0,x
LDMFDsp!,{r0} //不需要恢复寄存器
}
returnx;
}
将其进行改写,使它符合内联汇编的语法规则。
intf(intx)
{
intr0;
__asm
{
ADDr0,x,1
EORx,r0,x
}
returnx;
}
下面通过几个例子进一步了解内联汇编的语法。
①字符串拷贝
下面的例子使用一个循环完成了字符串的拷贝工作。
#includestdio.h>
voidmy_strcpy(constchar*src,char*dst)
{
intch;
__asm
{
loop:
LDRBch,[src],#1
STRBch,[dst],#1
CMPch,#0
BNEloop
}
}
intmain(void)
{
constchar*a=Helloworld!;
charb[20];
my_strcpy(a,b);
printf(Originalstring:'%s'\n,a);
printf(Copiedstring:'%s'\n,b);
return0;
}