【发布时间】:2014-02-15 22:23:45
【问题描述】:
当我尝试编译以下内容时,gcc 失败并显示
错误:'asm' 中的操作数约束不一致"
不幸的是,当我将函数拉入独立文件时,它编译得很好,所以我真的不确定问题出在哪里。该函数背后的想法是为用汇编语言编写的函数提供一个包装器,该包装器将强制执行预期的调用约定,而不管目标平台如何。
int wrap(int(*asmfn)(int,int,int,int), int param1, int param2, int param3, int param4) {
int x;
asm ( "push %1;" //save the input operand so it's not clobbered
"push %5;" //push the params RTL
"push %4;"
"push %3;"
"push %2;"
"call *%1;" //call the function
"pop %2;" //caller cleanup / restore the param operands so they are not clobbered
"pop %3;"
"pop %4;"
"pop %5;"
"pop %1;" //restore the other operand so it's not clobbered
"mov %%eax, %0;" //save the retval to a local
: "=X" (x)
: "c" (asmfn), "d" (param1), "b" (param2), "S" (param3), "D" (param4)
: "cc", "memory", "%eax" );
return x;
}
我尝试将输出操作数限制在仅内存或寄存器中,甚至将其专门限制在eax 中并从clobber 列表中删除“%eax”,但无论哪种方式我都会遇到相同的错误。我错过了什么?
【问题讨论】:
-
@KarolyHorvath 曾经有一个原因,但无论如何我仍然得到错误。我更新了这个问题,让它看起来不那么不寻常。
-
我认为这是反对,因为您正在使用所有可用的寄存器,然后说您正在破坏
%eax。您的列表中提到的唯一寄存器是%esp和%ebp,因此 %0 可能会存储在%eax- 因此,您也不能破坏%eax。 -
@MatsPetersson 我认为这可能是一个问题,这就是为什么我尝试了问题最后一段中的解决方法,但它仍然给出了同样的错误。作为一个实验,我还尝试从 clobber 列表中完全删除所有内容(尽管这显然会导致错误的代码)并且仍然得到错误。
-
啊哈,找到了问题,但 8 小时内无法将其作为答案发布...希望我会记得回来发布,以便其他遇到此问题的人可以找到答案.
-
Clang produces 一堆“指令要求:不是 64 位模式”的错误消息,而在 32 位模式下它确实是 appear to work。也许您需要在推送/弹出指令上使用不同的限定符?
标签: c++ g++ inline-assembly