首页 > 解决方案 > 裸函数中的 Asm 插入

问题描述

我有 ubuntu 16.04、x86_64 arch、4.15.0-39-generic 内核版本。海合会 8.1.0

我试图将这个函数(从第一篇文章https://groups.google.com/forum/#!topic/comp.lang.c++.moderated/qHDCU73cEFc)从英特尔方言重写为 AT&T。而我没有成功。

namespace atomic {
  __declspec(naked)
  static void*
  ldptr_acq(void* volatile*) {
    _asm {
      MOV EAX, [ESP + 4]
      MOV EAX, [EAX]
      RET
    }
  }

  __declspec(naked)
  static void*
  stptr_rel(void* volatile*, void* const) {
    _asm {
      MOV ECX, [ESP + 4]
      MOV EAX, [ESP + 8]
      MOV [ECX], EAX
      RET
    }
  }
}

然后我写了一个简单的程序,来获取相同的指针,我在里面传递。我安装了支持裸属性的 GCC 8.1 版(https://gcc.gnu.org/gcc-8/changes.html“x86端口现在支持裸函数属性”)用于功能。据我记得,这个属性告诉编译器不要创建函数的序言和结语,我可以自己从堆栈中取出参数并返回它们。代码:(不要使用段错误)

#include <cstdio>
#include <cstdlib>

  __attribute__ ((naked))
  int *get_num(int*) {
    __asm__  (
      "movl 4(%esp), %eax\n\t"
      "movl (%eax), %eax\n\t"
      "ret"
    );
  }

int main() {
    int *i =(int*) malloc(sizeof(int));
    *i = 5;

    int *j = get_num(i);
    printf("%d\n", *j);

    free(i);
    return 0;
}

然后我尝试使用 64 位寄存器:(不要使用 segfault)

__asm__  (
  "movq 4(%rsp), %rax\n\t"
  "movq (%rax), %rax\n\t"
  "ret"
);

只有在我从 rdi 寄存器中取出值之后 - 这一切都奏效了。

__asm__  (
  "movq %rdi, %rax\n\t"
  "ret"
);

为什么我无法通过堆栈寄存器进行传输?我可能犯了一个错误。请告诉我我的失败在哪里?

标签: c++gccassemblyx86-64calling-convention

解决方案


因为 x86-64 System V 调用约定在寄存器中传递 args,而不是在堆栈上,这与旧的低效 i386 System V 调用约定不同。

如果您在 asm 中编写整个函数,就像使用naked函数或独立.S文件一样,您总是必须编写符合调用约定的 asm。

GNU C 扩展 asm 允许您使用操作数来指定 asm 语句的输入,编译器将生成指令来实现这一点。(不过,在您了解 asm 以及编译器如何将 C 转换为启用优化的 asm 之前,我不建议您使用它。)


另请注意,movq %rdi, %rax实现long *foo(long*p){return p;}not return *p。也许您mov (%rdi), %rax的意思是取消引用指针 arg?


顺便说一句,您绝对不需要也不应该为此使用内联汇编。 https://gcc.gnu.org/wiki/DontUseInlineAsm,请参阅https://stackoverflow.com/tags/inline-assembly/info

在 GNU C 中,您可以将指针强制转换为volatile uint64_t*. 或者,您可以使用__atomic_load_n (ptr, __ATOMIC_ACQUIRE)基本上从该 asm 中获取所有内容,而无需函数调用的开销或调用站点的优化器的任何成本,即所有调用破坏的寄存器都被破坏。

您可以在任何对象上使用它们:https ://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html 与 C++11 不同,您只能在std::atomic<T>.


推荐阅读