[英]GCC inline ASM guarantees
我认为这是一个简单的问题,但我什么也找不到。 如果我写
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的值?
否-编译器根据约束将其in / out值连接到在asm语句之前/之后立即分配的寄存器/内存位置,并假定其他寄存器不受影响。 因此,在您的情况下,它可能已将重要内容放入您正在破坏的%%eax
或%%ebx
中(这可能导致崩溃或其他不良行为)。
每当您在asm语句中使用固定寄存器时,都必须在clobbers列表中列出这些寄存器(除非您使用的是映射到特定寄存器的约束)。 因此,至少您需要:
asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx) : "rax", "rbx");
为您的asm语句-但是即使这样,也无法保证编译器不会在您的第一个asm块之后和第二个asm块之前(%s试图保存的值)在%%eax
或%%ebx
放入其他内容。
在gcc中将volatile
与asm
一起使用将确保编译器不会重新排序状态。 但是,不能保证编译器不会在foo:
标签和内联asm
语句之间添加额外的代码。 当然,这意味着您不能依赖该部分中保留的寄存器值-我还没有提供一个独特的示例,但是我敢肯定编译器不保证这样做可以不会发生
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.