0

我认为这是一个简单的问题,但我找不到任何东西。如果我写

void bar()
{
    {
        void *rax = 0/* ...*/, *rbx = 0/* ... */;
        asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx));
        goto foo;    
    }

    {
        foo:
        void* rax, *rbx;
        asm volatile ("movq %%rax, %0; movq %%rbx, %1;" : "=m"(rax), "=m"(rbx));

        // LOTS OF CODE
    }
}

是否保证我可以在第二个块中的任何其他代码运行之前获取 rax/rbx 的值?

4

2 回答 2

3

不——编译器根据它在 asm 语句之前/之后分配的寄存器/内存位置的约束来连接输入/输出值,并假设其他寄存器不受影响。因此,在您的情况下,它可能会放入一些重要的东西%%eax%%ebx您正在破坏的东西(这可能会导致崩溃或其他不当行为)。

任何时候在 asm 语句中使用固定寄存器时,都必须在 clobbers 列表中列出这些寄存器(除非您使用映射到特定寄存器的约束)。所以至少你需要:

asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx) : "rax", "rbx");

对于您的 asm 语句-但即使那样,也不能保证编译器不会在您的第一个 asm 块中%%eax%%ebx之后以及第二个之前(破坏您要保存的值。)

于 2013-07-03T00:31:11.793 回答
1

在 gcc中使用volatilewithasm将保证编译器不会重新排序语句。但是,不能保证编译器不会在foo:标签和内联asm语句之间添加额外的代码。当然,这意味着您不能依赖保留在该部分中的寄存器值 - 我还没有设法提出一个独特的例子,但我很确定编译器不能保证这可以不会发生。

于 2013-07-03T09:21:06.697 回答