From: 杂项
用心感受,用心感受 - ..
一、GNU内联汇编中常用修饰符一览
修饰符 | 输入输出 | 含义 |
---|---|---|
= | O | 表示此Output操作表达式是只写的 |
+ | O | 表示此Output操作表达式是可读可写的 |
& | O | 表示此Output操作表达式独占为其指定的寄存器 |
% | I | 表示此Input操作表达式中的C/C++表达式可以与下一个Input操作表达式中的C/C++表达式互换 |
什么是占位符?
每一个占位符对应一个Input/Output操作表达式;
带C/C++表达式的内联汇编中有两种占位符,分别是序号占位符和名称占位符;
a.序号占位符
GCC规定一个内联汇编语句中最多只能有10个Input/Output操作表达式,这些操作表达式按照他们被列出来的顺序依次赋予编号0到9;对于占位符中的数字而言,与这些编号是对应的;比如:占位符%0对应编号为0的操作表达式,占位符%1对应编号为1的操作表达式,依次类推。
由于占位符前面要有一个百分号%,为了去边占位符与寄存器,GCC规定:在带有C/C++表达式的内联汇编语句的指令列表里列出的寄存器名称前面必须使用两个百分号(%%),一区别于占位符语法。
GCC对占位符进行编译的时候,会将每一个占位符替换为对应的Input/Output操作表达式所指定的寄存器/内存/立即数。
用一句话描述就是: 序号占位符就是前面描述的%0、%1、%2、%3、%4、%5、%6、%7、%8、%9`,其中,每一个占位符对应一个Input/Output的C/C++表达式;
2.名称占位符
由于GCC中限制这种占位符的个数最多只能由这10个,这也就限制了Input/Output操作表达式中C/C++表达式的数量做多只能有10个;如果需要的C/C++表达式的数量超过10个,那么,这些需要占位符就不够用了;
GCC内联汇编提供了名称占位符来解决这个问题;即:使用一个名字字符串与一个C/C++表达式对应;这个名字字符串就称为名称占位符;而这个名字通常使用与C/C++表达式中的变量完全相同的名字;
使用名字占位符时,内联汇编的Input/Output操作表达式中的C/C++表达式的格式如下:
[name] “constraint”(变量)
此时,指令列表中的占位符的书写格式如下:
%[name]
这个格式等价于序号占位符中的%0,%1,$2等等;
使用名称占位符时,一个name对应一个变量;
例如:
asm(“imull %[value1],%[value2]”
:[value2] “=r”(data2)
:[value1] “r”(data1),”0”(data2));
此例中,名称占位符value1就对应变量data1,名称占位符value2对应变量data2;GCC编译的时候,同样会把这两个占位符分别替换成对应的变量所使用的寄存器/内存地址/立即数;而且也增强了代码的可读性;
这个例子,使用序号占位符的写法如下:
asm(“imull %1,%0”
:”=r”(data2)
:”r”(data1),”0”(data2));
二、占位符的例子描述
最近在一段读地址的函数遇到了使用占位符的DEMO!
static __inline__ test(uint64_t phys, int cca)
{
uint64_t value = 0;
__asm__ __volatile__(".set push\n" /*压栈操作*/
".set noreorder\n" /*默认汇编器处于reorder模式下,切换到noreorder模式<指令的执行顺序不会被优化和改变>*/
".set mips64\n" /*设置指令集 mips64*/
"dli $8, " STR(NLH_XKPHYS) "\n" /*加载64位常数*/
"or $8, $8, %2\n" /*$8 = $8 | %2*/
"daddu $8, $8, %1\n" /*$8 = $8 + %1*/
"lw %0, 0($8) \n" /*%0 = *((long long *))$8*/ /*载入并将高位补0*/
".set pop\n" /*弹栈操作*/
:"=r"(value)
:"r"(phys & 0xfffffffffcULL),"r"((uint64_t) cca << 59)
:"$8");
return value;
}
上述代码怎么翻译呢?
$8 = $8 | %2 <==> $8 = $8 | cca << 59
$8 = $8 + %1 <==> 0x9000000000000000 + phys & 0xfffffffffcULL
%0 = *((long long *))$8 <==> value = *((long long *)$8)
也就是占位符%0 <==> value,占位符%1 <==> phys & 0xfffffffffcULL,占位符%2<==> cca << 59
By: Keven - 点滴积累