gcc内联汇编的奇怪行为

时间:2011-02-20 06:56:12

标签: gcc inline-assembly register-allocation

在gcc中内联程序集时,我发现自己经常需要添加空的asm块,以便在早期的块中保持变量存活,例如:

asm("rcr $1,%[borrow];"
    "movq 0(%[b_],%[i],8),%%rax;"
    "adcq %%rax,0(%[r_top],%[i],8);"
    "rcl $1,%[borrow];"
    : [borrow]"+r"(borrow)
    : [i]"r"(i),[b_]"r"(b_.data),[r_top]"r"(r_top.data)
    : "%rax","%rdx");

asm("" : : "r"(borrow) : ); // work-around to keep borrow alive ...

另一个奇怪的例子是,下面的代码在没有优化的情况下工作得很好,但是-O3就是seg-faults:

ulong carry = 0,hi = 0,qh = s.data[1],ql = s.data[0];
asm("movq 0(%[b]),%%rax;"
    "mulq %[ql];"
    "movq %%rax,0(%[sb]);"
    "movq %%rdx,%[hi];"
    : [hi]"=r"(hi)
    : [ql]"r"(ql),[b]"r"(b.data),[sb]"r"(sb.data)
    : "%rax","%rdx","memory");
for (long i = 1; i < b.size; i++)
{
    asm("movq 0(%[b],%[i],8),%%rax;"
        "mulq %[ql];"
        "xorq %%r10,%%r10;"
        "addq %%rax,%[hi];"
        "adcq %%rdx,%[carry];"
        "adcq $0,%%r10;"
        "movq -8(%[b],%[i],8),%%rax;"
        "mulq %[qh];"
        "addq %%rax,%[hi];"
        "adcq %%rdx,%[carry];"
        "adcq $0,%%r10;"
        "movq %[hi],0(%[sb],%[i],8);"
        "movq %[carry],%[hi];"
        "movq %%r10,%[carry];"
        : [carry]"+r"(carry),[hi]"+r"(hi)
        : [i]"r"(i),[ql]"r"(ql),[qh]"r"(qh),[b]"r"(b.data),[sb]"r"(sb.data)
        : "%rax","%rdx","%r10","memory");
}
asm("movq -8(%[b],%[i],8),%%rax;"
    "mulq %[qh];"
    "addq %%rax,%[hi];"
    "adcq %%rdx,%[carry];"
    "movq %[hi],0(%[sb],%[i],8);"
    "movq %[carry],8(%[sb],%[i],8);"
    : [hi]"+r"(hi),[carry]"+r"(carry)
    : [i]"r"(long(b.size)),[qh]"r"(qh),[b]"r"(b.data),[sb]"r"(sb.data)
    : "%rax","%rdx","memory");

我认为这与它使用如此多的寄存器这一事实有关。有没有我在这里缺少的东西,或者注册分配是否真的与gcc内联汇编错误?

1 个答案:

答案 0 :(得分:2)

你缺少的是GCC的优化器会假设asm块的唯一副作用是改变输出操作数。如果以后没有使用这些操作数,则可以假定asm块不必要,可以删除。

e.g。在您的第一个示例中,如果随后未使用borrow,则可以自由地假设根本不包含asm块,因为它唯一的副作用是更新变量从未再次使用过。在第二个示例中,如果在您显示的代码之后未再次使用hicarry,则可能会推断它几乎可以删除所有内容!

您可以通过编写asm volatile(...)而不是asm(...)来告知GCC不应删除您的内联汇编块。

有关详细信息,请参阅http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html(大约在页面的中间部分)。