9.2. 约束字符
约束字符位于输入操作数和输出操作数前,用于说明操作数类型、读写权限等属性。下面介绍常见约束字符。
“=”:修饰输出操作数,表示该操作数可写,原先的值会被丢弃,并由输出数据替换。
“+”:修饰输出操作数,表示该操作数可读可写。
“r”:表示该操作数是整型变量(用于修饰C语言中的
short、int、long等),请求编译器为其分配一个通用寄存器。“f”:请求分配一个浮点寄存器,用于修饰C语言中的浮点变量(
float或double)。例如,要实现浮点加法float ret = (float)a + (float)b;,可写为:
float ret = 0;
asm("fadd.s %0,%1, %2\n\t"
:"=f"(ret)
:"f"(a),"f"(b)
);
“I”:表示该操作数是有符号12位常量。当常数操作数小于12位时,可以使用该约束符。例如,实现带常数的加法:
asm("addi.w %0,%1\n\t"
:"=r"(ret)
:"r"(a),"I"(10)
);
“l”:表示该操作数是有符号16位常量。当常数操作数大于12位但小于16位时,可以考虑使用该约束符。
“K”:表示该操作数是无符号12位常量。当操作数为负数时,只能使用“I”或“l”;使用该约束符会报错。
“J”:表示该操作数是整数零。
“G”:表示该操作数是浮点数零。
“&”:表示该输出操作数是早期破坏操作数,即它的值可能在所有输入操作数使用完之前就被修改。
“m”:表示内存操作数,用于访存指令的地址加载和存储,常用于修饰C语言中的指针类型。例如,要把变量a的地址加载到指定寄存器t0,可写为:
int* p = &a;
asm("ld $t0, %0 \n\t"
: /*no output*/
:"m"(p)
:"$t0"
);