GCC内联ASM保证
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的值?
否--编译器根据asm语句之前/之后分配的寄存器/内存位置的约束,挂接输入/输出值,并假设其他寄存器不受影响。因此,在您的情况下,它可能会将一些重要的东西放入%%eax
或%%ebx
中,而您正在对此进行抨击(这可能会导致崩溃或其他不当行为)。
任何时候在asm语句中使用固定寄存器时,都必须在clobbers列表中列出这些寄存器(除非使用映射到特定寄存器的约束)。所以至少你需要:
asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx) : "rax", "rbx");
对于您的asm语句,但即使这样,编译器也不会提供任何保证在您的第一个asm块之后和第二个asm区块之前,将其他东西放入%%eax
或%%ebx
中(破坏您试图保存的值)
在gcc中将volatile
与asm
一起使用,将保证编译器不会重新排列状态。但是,不能保证编译器不会在foo:
标签和内联asm
语句之间添加额外的代码。当然,这意味着你不能依赖于在该部分中保留的寄存器值——我还没有想出一个明显的例子,但我很确定编译器不能保证这不会发生。
相关文章:
- 与互斥锁相比,旋转锁可以保证上下文切换
- 原子读取是否保证读取最新值
- C++:当所有条目都保证是唯一时,替代 std::map
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- 使用C++获取程序的 ASM
- "std::list::splice(std::const_iterator pos, std::list&& other)"是否保证将"其他"留空?
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- C++ 11 中的锁定是否保证访问数据的新鲜度?
- C++std::atomic在程序员级别保证了什么
- CUDA三角函数中的数学保证
- 标准是否保证无捕获的 lambda 为空?
- 是否可以保证按字节的零 int 是零的表示形式?
- 有没有办法保证析构函数的相对顺序?
- 单行函数模板 c++ 的内联性保证
- 在 c++ 中使用 x86 DIV 的这个 asm 块有什么用?
- C++易失性:保证 32 位访问?
- 迭代器在递增和递减时是否保证会变异?
- std::元组分配和复制/移动异常保证
- 保证编译器指令在C++中重新排序
- GCC内联ASM保证