【问题标题】:What is wrong with the following inline assembly?以下内联汇编有什么问题?
【发布时间】: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


【解决方案1】:

经过大量实验,我意识到了这个问题,以及为什么它在独立时不会导致错误:这是在代码被编译成共享对象时,因此启用了“-fPIC”。这导致 gcc 在函数入口处使用ebx 存储当前eip,以便它可以通过函数的相对偏移量(在编译时已知)找到 GOT,以便代码可以与位置无关。因此,PIC 中任何使用ebx 作为操作数的内联程序集都会产生这个完全不透明的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 2012-04-22
    • 2012-07-31
    相关资源
    最近更新 更多