【问题标题】:Why can't I use more than two registers in inline asm? [closed]为什么我不能在内联 asm 中使用两个以上的寄存器? [关闭]
【发布时间】:2020-04-25 11:18:31
【问题描述】:

我试图在我的部分代码中使用汇编,但我需要使用多个变量。为什么我不能为 C 变量使用两个以上的寄存器?

__asm(
"add %eex, %edx\n"
"add %eax, %ecx\n"
"mov 1 ,%0\n"
:"=r"(side)
:"a"(map.y));
:"e"(sdist.y)
:"d"(delta.y)
:"c"(step.y)
);

当我编译这个时,我得到了错误

a.c: In function ‘main’:
a.c:289:2: error: expected expression before ‘:’ token
  :"e"(sdist.y)
  ^
a.c:292:1: error: expected statement before ‘)’ token
  );

【问题讨论】:

  • 可能是这一行的尾随分号或额外的括号? :"a"(map.y));
  • ); 应该在编译器标记错误的地方吗?
  • 请注意,这里没有 EEX 寄存器,并且“e”约束并不表示寄存器操作数。
  • 这在很多其他方面都非常糟糕,包括语法(多个输入操作数应该用逗号分隔),1 是绝对地址1;也许您的意思是$1 立即数或%1 操作数?此外,x86 的 "e" 约束是适合 32 位符号扩展的立即数;没有eex 注册。您的其他输入约束都是特定的寄存器。 gcc.gnu.org/onlinedocs/gcc/…。哦,还有,这破坏了只读输入操作数(如 EDX 和 ECX)中的值,违反了约束。
  • TL:DR:请参阅 stackoverflow.com/tags/inline-assembly/info 获取指南和教程的链接。 使用 GNU C 内联 asm 将代码扔到墙上直到它粘住甚至比平时更糟糕:很容易(如果你得到约束甚至是微妙的错误)使代码恰好与一组正确工作周围的代码,但因不同的优化选项或对其他代码的微小更改而中断。在签署一段内联汇编之前,请确保您准确了解所有内容以及为什么它是安全的。或者不要使用它。

标签: c assembly cpu-registers


【解决方案1】:

对于那个特定错误,); 应该在你拥有它的地方(我在下面指出的地方)。

__asm(
"add %eex, %edx\n"
"add %eax, %ecx\n"
"mov 1 ,%0\n"
:"=r"(side)
:"a"(map.y));    <---
:"e"(sdist.y)
:"d"(delta.y)
:"c"(step.y)
);

它关闭了整个asm 语句,这也是在您的最后一行中完成的。 猜测我会说你刚刚添加了三个额外的寄存器edc,以及新的收盘线,但没有先调整原始收盘线 (注册a)。

不管为什么你这样做了,结果是:"e"(sdist.y)回到了C领域,因此无效。


即使您已经解决了直接的问题,您的代码中仍有许多其他错误,例如(可能不是详尽列表):

  • 多个输入操作数应以逗号分隔;
  • 1 是绝对地址 1 - 您可能打算将 $1 写为立即数,或将 %1 写为操作数;
  • x86 的 e 约束是适合 32 位符号扩展的立即数,并且没有 eex 寄存器;
  • 这会破坏只读输入操作数(如 edxecx)中的值,违反了约束条件。

【讨论】:

  • 还是出现同样的错误
  • @Russell356:就像我在问题下评论的那样,您的代码挤满了其他主要错误,包括语法错误。
  • @Peter,所有优秀的观点,我希望你不介意我将它们作为附录纳入答案(因为它使它更有用)。
  • 是的,这得到了我的支持 :) 该信息绝对属于答案。
猜你喜欢
  • 2016-04-03
  • 2013-07-04
  • 2018-10-05
  • 1970-01-01
  • 2017-01-13
  • 2019-11-30
  • 2010-11-18
  • 2013-04-12
相关资源
最近更新 更多