在扩展 asm 输出参数中使用“+”修饰符时输入参数索引?
Input parameter index when using "+" modifier in extended asm output parameter?
Extended asm 给出了以下关于 "+"
修饰符的描述:
Operands using the ‘+’ constraint modifier count as two operands (that
is, both as input and output) towards the total maximum of 30 operands
per asm statement.
所以我假设没有必要在输入部分再次提到带有“+”修饰符的输出操作数,但是没有指定如何确定它们的索引。我写了下面的例子 Godbolt :
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
void asm_add(uint64_t o1, uint64_t o2, uint64_t o3){
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1):
"cc"
);
printf("o2 = %" PRIu64 "\n", o2);
printf("o3 = %" PRIu64 "\n", o3);
}
int main(void){
asm_add(20, 30, 40);
}
哪个打印出来
o2 = 50
o3 = 60
模板是否使用+
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1):
"cc"
);
与
完全相同
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1), "0" (o2), "1" (o3):
"cc"
);
明确指定所有输入的位置?因此,在第一个示例中,附加了 "implicit" 输入。
通过使用 "+r" (o2)
,您是说该参数在进入 asm 块时需要包含 o2,并在退出时包含更新值。
换句话说,%0 描述了输入和输出。您可以(显然?)引用大于参数数量的索引是一个未记录的怪癖。不要依赖它。
您也可以考虑使用符号名称,(我发现)它们更易于阅读,尤其是随着 asm 行数的增加。当您第一次创建 asm 并且可能有 adding/removing 参数时,名称特别有用。必须对所有内容重新编号很痛苦且容易出错:
__asm__ volatile (
"addq %[o1], %[o2]\n\
addq %[o1], %[o3]":
[o2] "+r" (o2), [o3] "+r" (o3):
[o1] "r" (o1):
"cc"
);
最后,考虑 not using inline asm 用于教育目的之外的任何事情。即使那样,内联 asm 也是学习 asm 最难的方法。
Extended asm 给出了以下关于 "+"
修饰符的描述:
Operands using the ‘+’ constraint modifier count as two operands (that is, both as input and output) towards the total maximum of 30 operands per asm statement.
所以我假设没有必要在输入部分再次提到带有“+”修饰符的输出操作数,但是没有指定如何确定它们的索引。我写了下面的例子 Godbolt :
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
void asm_add(uint64_t o1, uint64_t o2, uint64_t o3){
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1):
"cc"
);
printf("o2 = %" PRIu64 "\n", o2);
printf("o3 = %" PRIu64 "\n", o3);
}
int main(void){
asm_add(20, 30, 40);
}
哪个打印出来
o2 = 50
o3 = 60
模板是否使用+
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1):
"cc"
);
与
完全相同__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1), "0" (o2), "1" (o3):
"cc"
);
明确指定所有输入的位置?因此,在第一个示例中,附加了 "implicit" 输入。
通过使用 "+r" (o2)
,您是说该参数在进入 asm 块时需要包含 o2,并在退出时包含更新值。
换句话说,%0 描述了输入和输出。您可以(显然?)引用大于参数数量的索引是一个未记录的怪癖。不要依赖它。
您也可以考虑使用符号名称,(我发现)它们更易于阅读,尤其是随着 asm 行数的增加。当您第一次创建 asm 并且可能有 adding/removing 参数时,名称特别有用。必须对所有内容重新编号很痛苦且容易出错:
__asm__ volatile (
"addq %[o1], %[o2]\n\
addq %[o1], %[o3]":
[o2] "+r" (o2), [o3] "+r" (o3):
[o1] "r" (o1):
"cc"
);
最后,考虑 not using inline asm 用于教育目的之外的任何事情。即使那样,内联 asm 也是学习 asm 最难的方法。