9.2. 约束字符

约束字符位于输入操作数和输出操作数前,用于说明操作数类型、读写权限等属性。下面介绍常见约束字符。

  • “=”:修饰输出操作数,表示该操作数可写,原先的值会被丢弃,并由输出数据替换。

  • “+”:修饰输出操作数,表示该操作数可读可写。

  • “r”:表示该操作数是整型变量(用于修饰C语言中的shortintlong等),请求编译器为其分配一个通用寄存器。

  • “f”:请求分配一个浮点寄存器,用于修饰C语言中的浮点变量(floatdouble)。例如,要实现浮点加法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"
);