在扩展的asm输出参数中使用“ +”修饰符时的输入参数索引?

时间:2019-10-08 10:13:35

标签: c gcc assembly inline-assembly

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"
);

所有输入都在哪里明确指定?因此,在第一个示例中,将添加“隐式”输入。

1 个答案:

答案 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的最困难的方法。