在了解内嵌汇编的具体使用方法之后,还有几点事项必须在编程时注意。
(1)必须小心使用物理寄存器。
在使用内嵌汇编程序设计方法时,必须要小心使用物理寄存器,主要指R0~R3、PC、LR寄存器,以及CPSR中的N、Z、C和V标志位等。因为在计算汇编代码中的C表达式时,可能会使用这些物理寄存器,并会修改N、Z、C和V标志位。
例如:
__asm
{
MOV var,x
ADD y,var,x/y
}
计算x/y时R0会被修改。内嵌汇编器探测到隐含的寄存器冲突就会报错。
(2)不要使用寄存器代替变量。
尽管有时寄存器明显对应某个变量,但也不能直接使用寄存器代替变量。
例如:
int bad_f(int x) //x存放在R0中
{
__asm
{
ADD R0,R0,#1
//发生寄存器冲突,实际上R0的值没有变化
}
return(x);
}
尽管根据编译器的编译规则R0对应x,但这样的代码会使内嵌汇编器认为发生了寄存器冲突。用其他寄存器代替R0存放参数x,使得该函数将x原封不动地返回。
这段代码的正确写法如下:
int bad_f(int x)
{ __asm
{
ADD x,x,#1
return(x);
}
}
(3)使用内嵌汇编无须保存和恢复寄存器。
事实上,除了CPSR和SPSR寄存器以外,对物理寄存器先读后写都会引起汇编器报错。
例如:
int f(int x)
{
__asm
{
STMFD SP!,{R0} //保存R0,先读后写,汇编出错
ADD R0,x,ll
EOR x,R0,x
LDMFD SP!,{R0}
}
return(x);
}
(4)LDM和STM指令的寄存器列表中只允许使用物理寄存器。
内嵌汇编可以修改处理器模式、协处理器模式及FP、SL、SB等APCS寄存器。但是编译器在编译时并不了解这些变化,因此必须保证在执行C代码前恢复相应被修改的处理器模式。
(5)汇编语言中的“,”号作为操作数分隔符。
如果有C表达式作为操作数,若表达式中包含有“,”,则必须使用符号“(”和“)”将其归约为一个汇编操作数。
例如:
__asm
{
ADD x,y,(f(),z) //"f(),z"为一个带有","的C表达式
}
关于ARM汇编语言编程中的ARM汇编伪指令介绍,以及ARM程序设计中的模块化程序设计、ARM汇编和C/C++的混合语言编程的介绍如上所述。接下来将分别探讨基于ARM处理器的底层驱动开发的方式。