我看过,如果我们在缓冲区列表中指定“ 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”,它在汇编输出中的作用是什么
对于x86,绝对没有。 对于x86和x86-64,每个cc
语句中都隐含asm()
破坏符。因为大多数x86指令都写了FLAGS,所以此设计决策具有一定意义。而且因为它很容易遗漏并且可能很难被测试抓住。 (尽管不乏在GNU C内联汇编中容易出错的地方。通常不需要使用它。)
((确实不可能告诉编译器何时您的asm语句does n't修改标志,但是这样做的成本可能很低,通常只需再执行一条指令即可重做比较或其他操作,或者保存变量,以便以后进行比较。)
如果您想做学究,可以在每个修改FLAGS的asm语句中使用"cc"
破坏符。
对于非x86,您必须在每个修改标志/条件代码(在具有它们的ISA上)的asm语句中使用cc
破坏符。例如ARM。在ARM上,设置标志是可选的。带S后缀的指令设置标志。因此,adds r0, r1, r2
根据r0 = r1+r2
设置标志,但add r0, r1, r2
保留标志不变。
[如果在非x86上遗漏了"cc"
破坏符,则编译器可能会在asm语句之前发出设置标志的asm,并在之后读取它们,作为实现其他一些非asm语句的一部分。因此,它本质上与破坏寄存器相同:无意义的行为取决于编译器使用寄存器或标志的详细信息,并且随优化级别和/或编译器版本的不同而不同。
这就是为什么测试不足以证明嵌入式组件安全的原因。使用一个编译器版本,您很容易会很幸运,让编译器生成的代码碰巧不会在asm语句中的状态寄存器/条件代码中保留任何内容,而是在函数中使用不同的编译器版本或周围的代码来内联容易受到错误的asm语句的影响。