Extended asm提供了有关"+"
修饰符的以下描述:
使用“ +”约束修饰符的操作数作为两个操作数(即 是,作为输入和输出),总共最多30个操作数 每个asm语句。
因此,我假设不必在输入部分中再次使用“ +”修饰符提及输出操作数,但是未指定如何确定其索引。我写了以下示例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"
);
所有输入都在哪里明确指定?因此,在第一个示例中,将添加“隐式”输入。
答案 0 :(得分:2)
通过使用"+r" (o2)
,您说此参数在进入asm块时需要包含o2,并在退出时包含更新的值。
换句话说,%0描述输入和输出。您可以(显然吗?)引用的索引大于参数的数量这一事实是一个未记录的怪癖。不要依赖它。
您还可以考虑使用符号名称,(我发现)符号名称更易于阅读,尤其是随着asm行数的增加。名称在首次创建asm时特别有用,并且有可能添加/删除参数。必须重新编号所有内容是痛苦且容易出错的:
__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的最困难的方法。