【问题标题】:What happens in the assembly output when we add "cc" to clobber list当我们将“cc”添加到 clobber 列表时,程序集输出中会发生什么
【发布时间】:2020-01-09 03:31:37
【问题描述】:

我读到,如果我们在 clobber 列表中指定“cc”,则表明汇编代码修改了标志寄存器

编写了一个示例程序来检查添加“cc”和不添加之间的区别。 当我们添加“cc”时,比较程序集没有变化。

#include <stdio.h>

int main(void)
{
        unsigned long sum;

        asm("incq %0" 
        : "=r"(sum)//output operand
        : "r" (sum) //input operand
    );
        printf("sum= %lu\n", sum);
        return 0;
}

我们什么时候应该使用“cc”,它在汇编输出中的作用是什么

【问题讨论】:

    标签: c gcc inline-assembly


    【解决方案1】:

    对于 x86,绝对没有。 对于 x86 和 x86-64,cc clobber 隐含在每个 asm() 语句中。这个设计决策是有道理的,因为大多数 x86 指令都写了 FLAGS。而且因为它很容易被忽略并且很难通过测试来捕捉。 (虽然 GNU C 内联汇编不乏容易出错的东西。通常不需要使用它。)

    (当你的 asm 语句 修改标志时,它确实无法告诉编译器,但这样做的成本可能很低,通常只需要多一条指令来重做比较或其他东西,或者保存一个变量,以便以后进行比较。)

    如果你想学究气,你可以在每个修改 FLAGS 的 asm 语句中使用 "cc" clobber。


    对于非 x86,您必须在每个修改标志/条件代码的 asm 语句中使用cc clobber(在具有它们的 ISA 上)。例如ARM。在 ARM 上,设置标志是可选的;带有 S 后缀的指令集标志。所以adds r0, r1, r2 根据r0 = r1+r2 设置标志,但add r0, r1, r2 保持标志不变。

    如果您遗漏了 "cc" clobber(在非 x86 上),编译器可能会发出 asm 在 asm 语句之前设置标志并在之后读取它们,作为实现其他非 asm 语句的一部分。因此它可能与销毁寄存器本质上相同:无意义的行为取决于编译器使用寄存器或标志的详细信息,并且随优化级别和/或编译器版本而变化。

    这就是为什么测试不足以证明内联汇编是安全的。使用一个编译器版本,您很容易走运,并且让编译器生成的代码碰巧不会在 asm 语句中的状态寄存器/条件代码中保留任何内容,而是在此内联的函数中使用不同的编译器版本或不同的周围代码容易受到错误的 asm 语句的影响。

    【讨论】:

    • 我开始怀疑了,作者其实可能是一个AI实现,它是所有已知的汇编知识的集合:)再次学习,谢谢彼得...
    猜你喜欢
    • 1970-01-01
    • 2016-11-30
    • 2011-01-24
    • 2017-11-27
    • 1970-01-01
    • 2019-11-16
    • 2014-03-31
    • 1970-01-01
    • 2015-04-22
    相关资源
    最近更新 更多