【问题标题】:converting gcc inline assembly to ml64将 gcc 内联汇编转换为 ml64
【发布时间】:2017-08-09 23:23:41
【问题描述】:

作为尝试实现对 cgo 的 msvc 支持的一部分,我发现我需要将一些内联 gcc 程序集移植到 ml64。这是原始程序集:

ts = *(ThreadStart*)v;

/*
 * Set specific keys in thread local storage.
 */
__asm {
      "movq %0, %%gs:0x28\n"    // MOVL tls0, 0x28(GS)
      "movq %%gs:0x28, %%rax\n" // MOVQ 0x28(GS), tmp
      "movq %1, 0(%%rax)\n" // MOVQ g, 0(GS)
      :: "r"(ts.tls), "r"(ts.g) : "%rax"
}

这是我创建的外部汇编文件:

PUBLIC msvc_windows_amd64_threadentry

.CODE
    msvc_windows_amd64_threadentry PROC

        MOV gs:[0x28], ts.tls
        MOV rax, gs:[0x28]
        MOV gs:[0], ts.g

        ret
    msvc_windows_amd64_threadentry ENDP
END

显然存在一些问题。一方面,我现在不知道如何让汇编器知道ts 的结构; gcc 显然知道它,因为它在正在编译的文件中,但 msvc 不支持 amd64 内联汇编。另一个是我认为我可以像其他任何extern 函数一样调用msvc_windows_amd64_threadentry,但我并不完全确定。老实说,我从来没有过多地处理装配问题,所以我以前从未遇到过这些问题。

【问题讨论】:

  • 您遇到的主要问题是这是针对 linux 线程本地存储的。 Windows 线程本地存储完全不同,因此即使您可以让该程序集与您的编译器一起使用,它也不会在 Windows 上运行。
  • 完全取决于你想要做什么。如果您不介意依赖 C11,请重写代码以使用 thread_local
  • “原始程序集”示例中的内联程序集过于复杂。只有第一个汇编语句需要在内联汇编中,最后两个语句可以用纯 C 编码。第三个语句也与同一行给出的注释不匹配。
  • 实际上,澄清一下,当我说“gcc”时,我指的是 MinGW,似乎 GS 用于 win_amd64 上的线程本地存储。您确定这不会在 Windows 上正常运行吗?我认为 MinGW 还不够先进,无法重写程序集。
  • 你知道原始代码是否真的可以在Windows上运行吗?看起来写它的人不太清楚自己在做什么。

标签: c gcc assembly visual-c++


【解决方案1】:

您根本不需要使用汇编来将此代码移植到 Microsoft C++。您可以使用 __writegsqword 内在函数替换第一条汇编指令,然后使用纯 C 替换最后两条汇编指令。例如:

__writegsqword(0x28, (unsigned long long) ts.tls);
*(void **)ts.tls = (void *) ts.g;

请注意,根据 ts.tlsts.g 的类型,您可能最好使用不同的演员表,或者完全避免使用它们。

您可以通过添加如下函数将相同的代码用于 GCC 和 Microsoft C++:

#ifdef __GNUC__
static inline void
__writegsqword(unsigned long long offset, unsigned long long value) {
    asm("movq %0,%%gs:%1" :: "re" (value), "m" (*(int *)offset));
}
#endif

【讨论】:

  • 非常感谢。我并不期待管理外部程序集文件。
猜你喜欢
  • 2016-10-07
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 2012-10-20
  • 2019-05-11
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多