内联汇编语法
语法
(1)asm
? 这块直接写做
__asm__
? 表示这是一段内联汇编。
(2)asm-qualifiers
? 这里取值有三种 volatile , inline , goto:
? volatile的意思是易变的、不稳定的,用来告诉编译器不要随便优化这段代码,否则可能出问题。比如汇编指令“mov r0, r0”,它把r0的值复制到r0,并没有实际做什么事情,你的本意可能是用这条指令来延时。编译器看到这指令后,可能就把它去掉了。加上volatile的话,编译器就不会擅自优化。
(3)AssemblerTemplate
? 汇编指令,用双引号包含起来,每条指令用“\n”分开,比如:
"mov %0 , %1\n"
"add %0 , %1 ,%2\n"
**(4)OutputOperands **
? 输出操作数,内联汇编执行时,输出的结果保存在哪里。格式如下,当有多个变量时,用逗号隔开:
[ [asmSymbolicName] ] constraint (cvariablename)
asmSymbolicName 是符号名 ,随便取,也可以不写
constraint表示约束,有如下常用取值:
constraint | 描述 |
---|
m | memory operand,表示要传入有效的地址,只要CPU能支持该地址,就可以传入 | r | register operand,寄存器操作数,使用寄存器来保存这些操作数 | i | immediate integer operand,表示可以传入一个立即数 |
cvariablename:C语言的变量名。
? 示例1如下:
[result] "=r" (sum)
? 它的意思是汇编代码中会通过某个寄存器把结果写入sum变量。在汇编代码中可以使用“%[result]”来引用它。
? 示例2如下:
"=r" (sum)
? 在汇编代码中可以使用“%0”、“%1”等来引用它,这些数值怎么确定后面再说。
(5)InputOperands
? 入操作数,内联汇编执行前,输入的数据保存在哪里。格式如下,当有多个变量时,用逗号隔开:
[ [asmSymbolicName] ] constraint (cexpression)
? asmSymbolicName是符号名,随便取,也可以不写。
? constraint表示约束,参考上一小节,跟OutputOperands类似。
cexpression:C语言的表达式。
? 示例1如下:
[a_val]"r"(a), [b_val]"r"(b)
? 它的意思变量a、b的值会放入某些寄存器。在汇编代码中可以使用%[a_val]、%[b_val]使用它们。
? 示例2如下:
"r"(a), "r"(b)
? 它的意思变量a、b的值会放入某些寄存器。在汇编代码中可以使用%0、%1等使用它们,这些数值后面再说。
(6)Clobbers
? 在汇编代码中,对于“OutputOperands”所涉及的寄存器、内存,肯定是做了修改。但是汇编代码中,也许要修改的寄存器、内存会更多。比如在计算过程中可能要用到r3保存临时结果,我们必须在“Clobbers”中声明r3会被修改。
? 下面是一个例子:
: "r0", "r1", "r2", "r3", "r4", "r5", "memory"
? 我们常用的是有“cc”、“memory”,意义如下:
Clobbers | 描述 |
---|
cc | 表示汇编代码会修改“flags register” | memory | 表示汇编代码中,除了“InputOperands”和“OutputOperands”中指定的之外, 还会读、写更多的内存 |
实践
? (1)首先来分析一个累加汇编函数
int add(int a, int b)
{
int sum;
__asm__ volatile (
"add %0, %1, %2"
:"=r"(sum)
:"r"(a), "r"(b)
:"cc"
);
return sum;
根据上述的语法进行分解
(1) __asm__
(2) volatile
(3) add %0, %1, %2
(4) "=r"(sum)
(5) "r"(a), "r"(b)
(6) "cc"
? (2)进阶版, 已知 在ARMv8架构中 的异常等级分为 EL0,EL1,EL2,EL3 ,想从 EL0 通过 EL3 必须使用 “smc #0”指令
,并且需要配置 r0, r1 ,r2 ,r3 , r4 , r5这些寄存器充当传参,在EL3执行完相应的服务后会将返回值返回到寄存器r0,如何实现该功能?
? 先分解条件
(1) __asm__
(2) volatile
(3) ldr r0 , =%[val0]
ldr r1 , =%[val1]
ldr r2 , =%[val2]
ldr r3 , =%[val3]
ldr r4 , =%[val4]
ldr r5 , =%[val5]
smc #0
mov %[result],r0
(4) [result]"=r"(ret)
(5) [val0]"r"(a0),[val1]"r"(a1),[val2]"r"(a2),[val3]"r"(a3),[val4]"r"(a4),[val5]"r"(a5)
(6) "r0"
内联汇编
unsigned int smc(unsigned int a0, unsigned int a1, unsigned int a2, unsigned int a3, unsigned int a4, unsigned int a5)
{
unsigned int ret;
__asm__ volatile(
"ldr r0 , =%[val0]\n"
"ldr r1 , =%[val1]\n"
"ldr r2 , =%[val2]\n"
"ldr r3 , =%[val3]\n"
"ldr r4 , =%[val4]\n"
"ldr r5 , =%[val5]\n"
"smc #0\n"
"mov %[result],r0\n"
:[result]"=r"(ret)
:[val0]"r"(a0),[val1]"r"(a1),[val2]"r"(a2),[val3]"r"(a3),[val4]"r"(a4),[val5]"r"(a5)
:"r0"
);
return ret;
}
|