当我们添加“时,程序集输出中会发生什么?”;cc";重击名单

当我们添加“时,程序集输出中会发生什么?”;cc";重击名单,c,gcc,inline-assembly,C,Gcc,Inline Assembly,我读到,如果我们在clobber列表中指定“cc”,则表示汇编代码修改了标志寄存器 编写了一个示例程序来检查添加“cc”和不添加之间的差异。 当我们添加“cc”时,比较程序集没有变化 #包括 内部主(空) { 无符号长和; asm(“增量%0” :“=r”(总和)//输出操作数 :“r”(总和)//输入操作数 ); printf(“sum=%lu\n”,sum); 返回0; } 我们什么时候应该使用“cc”,它在x86的汇编输出中有什么影响,绝对没有对于x86和x86-64,每个asm()语句

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

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

#包括
内部主(空)
{
无符号长和;
asm(“增量%0”
:“=r”(总和)//输出操作数
:“r”(总和)//输入操作数
);
printf(“sum=%lu\n”,sum);
返回0;
}

我们什么时候应该使用“cc”,它在x86的汇编输出中有什么影响,绝对没有对于x86和x86-64,每个
asm()
语句中都隐含着一个
cc
clobber。
此设计决策有一定意义,因为大多数x86指令都编写标志。而且因为它很容易被忽略,而且很难通过测试获得。(虽然GNU C内联asm并不缺少容易出错的东西,但通常不需要使用它。)

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

如果你想学究气,你可以在每个修改标志的asm语句中使用一个“
”cc“
”clobber


对于非x86,必须在每个修改标志/条件代码的asm语句(在具有标志/条件代码的ISA上)中使用
cc
clobber。e、 g.手臂
。在ARM上,设置标志是可选的;带有S后缀的指令集标志。因此
添加r0、r1、r2
根据
r0=r1+r2
设置标志,但是
添加r0、r1、r2
使标志保持不变

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


这就是为什么测试不足以证明内联asm是安全的。有了一个编译器版本,您就很容易幸运了,让编译器生成的代码恰好没有在asm语句的状态寄存器/条件代码中保留任何内容,但是不同的编译器版本或函数中不同的外围代码,这些内联线可能容易受到错误asm语句的攻击。

我开始怀疑,作者可能实际上是一个AI实现,它是所有已知汇编知识的集合。:)再次学习,谢谢你,彼得。。。
#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;
}