【问题标题】:Inline Assembly Stack Behavior内联汇编堆栈行为
【发布时间】:2014-12-19 16:16:05
【问题描述】:

我正在尝试将我的汇编代码集成到 c 程序中以使其更易于访问。 我尝试运行以下代码(我使用的是 x64 64 位架构)

 void push(long address) {
      __asm__ __volatile__("movq %0, %%rax;"
                            "push %%rax"::"r"(address));
 }

$rsp 的值似乎没有改变(尤其是在这方面也没有改变)。我是否遗漏了一些关于约束如何工作的明显内容? rax 已正确分配地址,但地址似乎从未被推入堆栈?

【问题讨论】:

  • 我猜编译器会为您的函数生成一个序言和结语,以保存和恢复堆栈指针。你可能需要标记它naked

标签: c gcc assembly stack


【解决方案1】:

你不能这样做。

内联汇编必须向编译器记录它接受的输入、产生的输出以及它在执行过程中破坏的任何其他状态。你没有这样做,但也许更重要的是,你不可能像你正在做的那样破坏堆栈指针,因为周围的代码,当它在 asm 块之后重新获得控制权时,将没有找到它的任何数据的方法 - 即使它已经将它保存在堆栈中,知道它会被破坏,它也无法取回它。

我不确定您要做什么,但无论如何,这不是这样做的方法。

【讨论】:

  • 当你说clobbering时,这意味着在这种情况下,我应该把rax,rsp写成被clobbered? (假设我现在对我的程序段错误很好。我只是想了解行为。我的理解是 asm 块不是函数,因此没有堆栈帧或返回地址。)
  • 正如我所说,绝对没有办法做你想做的事。即使你可以表明你要破坏堆栈指针,周围的代码也无法继续处理它。如果它确实有办法恢复它,它会撤消您尝试执行的操作。
  • 我认为您的困惑是假设您可以将单个推送作为一个函数(甚至是内联 asm 语句)。相反,无论出于何种目的将数据压入堆栈,您都需要在一个单独的 asm 块中完成整个操作,其中堆栈调整是平衡的,以便块的末尾,堆栈指针正是您在开始了。
  • 有道理,我是在多个块中进行的(然后跳跃)。
猜你喜欢
  • 2012-05-14
  • 2018-07-28
  • 2014-12-10
  • 2022-01-16
  • 1970-01-01
  • 2022-11-06
  • 1970-01-01
  • 2017-11-18
  • 1970-01-01
相关资源
最近更新 更多