当我们添加"cc"时,在汇编输出中会发生什么?到清单清单 [英] What happens in the assembly output when we add "cc" to clobber list

查看:70
本文介绍了当我们添加"cc"时,在汇编输出中会发生什么?到清单清单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解到,如果在垃圾清单中指定"cc",则表明汇编代码会修改标志寄存器

编写一个示例程序,以检查添加"cc"与不添加之间的区别.比较程序集时,我们添加"cc"没有任何改变.

  #include< stdio.h>int main(无效){无符号长整数;asm("incq%0":"= r"(sum)//输出操作数:"r"(sum)//输入操作数);printf("sum =%lu \ n",sum);返回0;} 

什么时候应该使用"cc",它在程序集输出中的作用是什么?

解决方案

对于x86,绝对没有.对于x86和x86-64,每个 asm()语句中都隐含一个 cc 闭包.该设计决策之所以有意义,是因为大多数x86指令写道.而且因为它很容易遗漏,并且可能很难被测试抓住.(尽管不乏在GNU C内联汇编中容易出错的地方.通常不需要使用它.)

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

如果您想学究脚,您可以在每个修改FLAGS的asm语句中使用"cc" 破坏符.


对于非x86,必须必须在修改标志/条件代码的每个asm语句中使用 cc 破坏符(在具有它们的ISA上).例如ARM .在ARM上,设置标志是可选的.带S后缀的指令设置标志.因此添加r0,r1,r2 会根据 r0 = r1 + r2 设置标志,但是添加r0,r1,r2 会保留标志不变.

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

这就是为什么测试不足以证明嵌入式asm安全的原因.使用一个编译器版本,您很容易会很幸运,让编译器生成的代码碰巧不在asm语句中的状态寄存器/条件代码中保留任何内容,而是在函数中使用了不同的编译器版本或不同的周围代码,从而可以内联容易受到错误的asm语句的攻击.<​​/p>

I read that if we specify "cc" in clobber list it indicates that an assembler code modifies flags register

Wrote a sample program to check the difference in between adding "cc" and not adding. Comparing the assembly there is no change when we add "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;
}

When should we use "cc", and what is the effect of it in the assembly output

解决方案

For x86, absolutely nothing. For x86 and x86-64, a cc clobber is implicit in every asm() statement. This design decision makes some sense because most x86 instructions wrote FLAGS. And because it's easy to miss and could be hard to catch with testing. (Although there's no shortage of things that are easy to get wrong with GNU C inline asm. There's usually no need to use it.)

(It does make it impossible to tell the compiler when your asm statement doesn't modify flags, but the cost of that is probably low, usually just one more instruction to redo a compare or something, or to save a variable so it can be compared later.)

If you want to be pedantic, you can use a "cc" clobber in every asm statement that modifies FLAGS.


For non-x86, you must use a cc clobber in every asm statement that modifies flags / condition codes (on ISAs that have them). e.g. ARM. On ARM, setting flags is optional; instructions with an S suffix set flags. So adds r0, r1, r2 sets flags according to r0 = r1+r2, but add r0, r1, r2 leaves flags untouched.

If you left out a "cc" clobber (on non-x86), the compiler might emit asm that set flags before an asm statement and read them afterwards, as part of implementing some other non-asm statement. So it could be essentially the same as destroying a register: nonsensical behaviour that depends on the details of what the compiler was using the register or the flags for, and which varies with optimization level and/or compiler version.

This is why testing isn't sufficient to prove inline asm is safe. With one compiler version, you could easily get lucky and have the compiler generate code that happened not to keep anything in the status register / condition codes across an asm statement, but a different compiler version or different surrounding code in a function where this inlines could be vulnerable to a buggy asm statement.

这篇关于当我们添加"cc"时,在汇编输出中会发生什么?到清单清单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆