md.*_*mal 4 c gcc inline-assembly
我读到,如果我们在 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;
}
Run Code Online (Sandbox Code Playgroud)
我们什么时候应该使用“cc”,它在汇编输出中的作用是什么
对于 x86,绝对没有。 对于 x86 和 x86-64,cc每个asm()语句中都隐含了一个clobber 。 这个设计决定是有道理的,因为大多数 x86 指令都写了 FLAGS。而且因为它很容易错过,并且很难通过测试发现。(尽管 GNU C 内联汇编不乏容易出错的东西。通常不需要使用它。)
(当你的 asm 语句不修改标志时,它确实无法告诉编译器,但这样做的成本可能很低,通常只需要多一条指令来重做比较或其他东西,或者保存一个变量,这样它就可以稍后比较。)
如果你想学究,你可以"cc"在每个修改 FLAGS 的 asm 语句中使用clobber。
对于非 x86,您必须cc在每个修改标志/条件代码的 asm 语句中使用clobber(在具有它们的 ISA 上)。例如 ARM。在 ARM 上,设置标志是可选的;带有 S 后缀设置标志的指令。因此adds r0, r1, r2根据 设置标志r0 = r1+r2,但add r0, r1, r2保持标志不变。
如果你遗漏了一个"cc"clobber(在非 x86 上),编译器可能会发出 asm,在 asm 语句之前设置标志并在之后读取它们,作为实现其他一些非 asm 语句的一部分。因此它可能与销毁寄存器本质上相同:无意义的行为取决于编译器使用寄存器或标志的详细信息,并且随优化级别和/或编译器版本而异。
这就是为什么测试不足以证明内联 asm 是安全的。使用一个编译器版本,您很容易走运并让编译器生成的代码碰巧不会在 asm 语句中的状态寄存器/条件代码中保留任何内容,但在一个函数中使用不同的编译器版本或不同的周围代码,该内联可以容易受到错误的 asm 语句的影响。
| 归档时间: |
|
| 查看次数: |
533 次 |
| 最近记录: |