Cha*_*l72 17 c c++ gcc constraints inline-assembly
我很难理解角色约束在GCC内联汇编(x86)中的作用.我已经阅读了手册,它准确地解释了每个约束的作用.问题在于,即使我理解每个约束的作用,我也很少理解为什么要使用一个约束而不是另一个约束,或者含义可能是什么.
我意识到这是一个非常广泛的话题,所以一个小例子应该有助于缩小焦点.以下是一个简单的asm例程,它只添加了两个数字.如果发生整数溢出,则将值写入1输出C变量.
int32_t a = 10, b = 5;
int32_t c = 0; // overflow flag
__asm__
(
"addl %2,%3;" // Do a + b (the result goes into b)
"jno 0f;" // Jump ahead if an overflow occurred
"movl $1, %1;" // Copy 1 into c
"0:" // We're done.
:"=r"(b), "=m"(c) // Output list
:"r"(a), "0"(b) // Input list
);
Run Code Online (Sandbox Code Playgroud)
现在这个工作正常,除了我必须随意摆弄约束,直到我让它正常工作.最初,我使用了以下约束:
:"=r"(b), "=m"(c) // Output list
:"r"(a), "m"(b) // Input list
Run Code Online (Sandbox Code Playgroud)
请注意,我使用"m"约束而不是"0" b.这有一个奇怪的副作用,如果我用优化标志编译并调用该函数两次,由于某种原因,加法操作的结果也将被存储c.我最终读到了" 匹配约束 ",它允许您指定变量将用作输入和输出操作数.当我改变"m"(b)到"0"(b)它的工作.
但我真的不明白为什么你会使用一个约束而不是另一个约束.我的意思是,是的,我知道,"R"是指变量应该是在寄存器和"m"意味着它应该是在内存中-但我并不真正理解什么选择一个对另一个的影响是,为什么加如果我选择某种约束组合,则操作无法正常工作.
问题:1)在上面的示例代码,为什么到"m"的约束b事业c得到写入?2)是否有任何教程或在线资源更详细地介绍约束?
Chr*_*ung 15
这里有一个例子来更好地说明为什么你应该仔细选择约束(与你的相同的功能,但也许更简洁地写一下):
bool add_and_check_overflow(int32_t& a, int32_t b)
{
bool result;
__asm__("addl %2, %1; seto %b0"
: "=q" (result), "+g" (a)
: "r" (b));
return result;
}
Run Code Online (Sandbox Code Playgroud)
因此,所使用的制约因素:q,r,和g.
q装置只eax,ecx,edx,或ebx可能被选择.这是因为set*指令必须写一个8位寻址寄存器(al,ah,...).使用b在%b0装置中,使用最低8位部分(al,cl,...).m或g两者兼而有之; 使用r的操作数的至少一个.g(一般).在上面的例子中,我选择使用g(而不是r)a因为引用通常被实现为内存指针,所以使用r约束将需要先将指示对象复制到寄存器,然后再复制回来.使用时g,可以直接更新指示对象.
至于你的原始版本c用附加值覆盖了你的原因,那是因为你=m在输出槽中指定了,而不是(比如说)+m; 这意味着允许编译器为输入和输出重用相同的内存位置.
在您的情况下,这意味着两个结果(因为相同的内存位置用于b和c):
c被覆盖了b(添加的结果)的值.c变为1(也b可能变为1,具体取决于代码的生成方式).